什么时候应该使用OpenGL的顶点索引数组? [英] When should I use indexed arrays of OpenGL vertices?

查看:305
本文介绍了什么时候应该使用OpenGL的顶点索引数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让我的时候,应使用OpenGL的顶点索引数组的一个清晰的思路,与GL [多] DrawElements画之类的,对我应该简单地使用顶点数组相邻,与GL [画多] DrawArrays。

更新:在我得到的答复一致认为每个人都应该使用索引顶点)

我已经来回在这个问题上几次,所以我将概述我目前的理解,同时希望在有人可以告诉我,我现在终于或多或少正确的,要不然指出我哪里其余的误解。具体来说,我有三个结论,大胆。请纠正他们,如果他们错了。

一个简单的例子是,如果我的几何图形组成的网格,形成曲面。在这种情况下,在网状的中间顶点将具有为它使用顶点每个三角形相同属性(位置,法线,色彩,纹理坐标等)。

这使我得出这样的结论:

1。对于一些接缝的几何形状,索引的数组是一大胜利。

请按照规则1一如既往,除了:

有关几何形状是非常块状,其中每边重新presents一个接缝,索引数组的好处是不太明显的。举一个简单的立方体作为一个例子,虽然每个顶点在三个不同的面使用,我们不能在它们之间共享的顶点,因为对于一个顶点,表面法线(和可能的其它东西,如颜色和质地共奥德)将每个面不同。因此,我们需要明确地引入冗余顶点位置到我们的阵列,使得相同的位置可以用不同的法线多次使用,等等。这意味着索引数组较少使用的

例如。当渲染一个立方体的一个面上:

  0 1
  ØØ---
  | \\ |
  | \\ |
  | \\ |
  ØØ---
 3 2

(在此可以单独考虑,因为这面和所有相邻面之间的接缝意味着比没有这些顶点可以面之间被共享)

如果使用GL_TRIANGLE_FAN(或_STRIP)渲染,那么立方体的每一面可以这样呈现:

 绿党= [V0,V1,V2,V3]
颜色= [C0,C0,C0,C0]
正常= [N0,N0,N0,N0]

添加索引不允许我们对此进行简化。

由此我得出这样的结论:

2。当渲染几何这是所有接缝或接缝大多使用GL_TRIANGLE_STRIP或_FAN的时候,那么我不应该使用索引数组,而是应该使用GL [多图] DrawArrays。

更新:回复表示,这一结论是错误的虽然指数不允许我们在这里降低了数组的大小,他们仍然应该使用,因为其他性能优势,如在评论中讨论)

排除2唯一的例外是:

当使用GL_TRIANGLES(代替条或风扇),那么顶点的一半仍然可以重新使用两次,用相同的法线和颜色,等等,因为每个立方体面呈现为两个不同的三角形。再次,对于相同的单个立方体面

  0 1
  ØØ---
  | \\ |
  | \\ |
  | \\ |
  ØØ---
 3 2

如果没有索引,使用GL_TRIANGLES,数组会是这样的:

 绿党= [V0,V1,V2,V2,V3,V0]
法线= [N0,N0,N0,N0,N0,N0]
颜色= [C0,C0,C0,C0,C0,C0]

由于顶点和正常通常每3浮子,和一个色往往是3个字节,即给出,为每个立方体的脸,大约

 绿党= 6 * 3 =花车彩车18
法线= 6 * 3 =花车彩车18
颜色= 6 * 3 =字节18字节= 36彩车和每个立方体表面18个字节。

(我理解的字节数可能会发生变化,如果使用不同的类型,确切的数字只是一个例子。)

使用指数,我们可以简化一点,赠送:

 绿党= [V0,V1,V2,V3(4 * 3 = 12个浮点)
法线= [N0,N0,N0,N0(4 * 3 = 12个浮点)
颜色= [C0,C0,C0,C0](4 * 3 = 12个字节)
指数= [0,1,2,2,3,0](6短裤)= 24 +彩车12个字节,也许6短裤,每个立方体的脸。

请参阅如何在后一种情况下,顶点0和2使用了两次,但只再在每个绿党,法线和颜色阵列的psented一旦$ P $。这听起来像一个小赢为使用指标,甚至在每一个几何边缘处的接缝的极端情况。

这使我得出这样的结论:

3。当使用GL_TRIANGLES,每个人都应该使用索引数组,甚至几何这是所有接缝。

请纠正我的结论大胆,如果他们错了。


解决方案

  

由此我得出结论,呈现几何形状,所有接缝或大部分接缝,使用时GL_TRIANGLE_STRIP或_FAN,那么我不应该使用索引数组,而是应该使用GL [多] DrawArrays时。


没有,原因很简单。

您结论是建立在你已经分析了由两个三角形组成的一个四的事实。使用三角风扇/条绘制这两个三角形不能使用索引的数组来简化。

但去想想一个大地形的几何形状。每个地形块被绘制成四,使用三角风扇/条原始。例如:

图中的每个三角形带中常见的有与相邻三角带所有顶点,并利用指数允许COM preSS的几何定义,而不是重复顶点每个三角形地带。


基本上,绘制图元使用指数(三角形,风扇和带)是有用的,只要你可以与另一个共享大多数单一原始的顶点。

共享信息允许以保存信息的传输带宽,但它不是唯一的优势。其实索引阵列允许:


  • 避免的属于相同的概念的顶点的信息的同步,指定多次

  • 允许对单个顶点进行相同的着色器操作,而不是执行多次,每一个顶点重复。

  • 此外,结合使用的三角形带/风扇和指数让PSS的索引缓冲区中的应用COM $ P $,由于带材/风扇规格要求较少指数(三角形总是3指标要求每个面)。

索引数组不能用,因为你已经指定,每当一个顶点不能共享与其他一致的顶点与它(颜色,纹理COORDS等)相关的所有信息。


只是为了完整起见,信息所必需的几何规格大小不是唯一的因素至极确定最佳渲染操作

逸岸,对于基本呈现的另一个基本因素是数据的高速缓存定位。严重指定的几何数据(非交错缓冲区对象,长三角条......)会导致很多缓存未命中,从而降低显卡的性能。

为了优化渲染操作,顶点说明书应的方式重用previously指定顶点重排序,以最概率。在这种方式中,显卡的高速缓存行可以重用previously指定点无需从内存中获取它们。

I'm trying to get a clear idea of when I should be using indexed arrays of OpenGL vertices, drawn with gl[Multi]DrawElements and the like, versus when I should simply use contiguous arrays of vertices, drawn with gl[Multi]DrawArrays.

(Update: The consensus in the replies I got is that one should always be using indexed vertices.)

I have gone back and forth on this issue several times, so I'm going to outline my current understanding, in the hopes someone can either tell me I'm now finally more or less correct, or else point out where my remaining misunderstandings are. Specifically, I have three conclusions, in bold. Please correct them if they are wrong.

One simple case is if my geometry consists of meshes to form curved surfaces. In this case, the vertices in the middle of the mesh will have identical attributes (position, normal, color, texture coord, etc) for every triangle which uses the vertex.

This leads me to conclude that:

1. For geometry with few seams, indexed arrays are a big win.

Follow rule 1 always, except:

For geometry that is very 'blocky', in which every edge represents a seam, the benefit of indexed arrays is less obvious. To take a simple cube as an example, although each vertex is used in three different faces, we can't share vertices between them, because for a single vertex, the surface normals (and possible other things, like color and texture co-ord) will differ on each face. Hence we need to explicitly introduce redundant vertex positions into our array, so that the same position can be used several times with different normals, etc. This means that indexed arrays are of less use.

e.g. When rendering a single face of a cube:

 0     1
  o---o
  |\  |
  | \ |
  |  \|
  o---o
 3     2

(this can be considered in isolation, because the seams between this face and all adjacent faces mean than none of these vertices can be shared between faces)

if rendering using GL_TRIANGLE_FAN (or _STRIP), then each face of the cube can be rendered thus:

verts  = [v0, v1, v2, v3]
colors = [c0, c0, c0, c0]
normal = [n0, n0, n0, n0]

Adding indices does not allow us to simplify this.

From this I conclude that:

2. When rendering geometry which is all seams or mostly seams, when using GL_TRIANGLE_STRIP or _FAN, then I should never use indexed arrays, and should instead always use gl[Multi]DrawArrays.

(Update: Replies indicate that this conclusion is wrong. Even though indices don't allow us to reduce the size of the arrays here, they should still be used because of other performance benefits, as discussed in the comments)

The only exception to rule 2 is:

When using GL_TRIANGLES (instead of strips or fans), then half of the vertices can still be re-used twice, with identical normals and colors, etc, because each cube face is rendered as two separate triangles. Again, for the same single cube face:

 0     1
  o---o
  |\  |
  | \ |
  |  \|
  o---o
 3     2

Without indices, using GL_TRIANGLES, the arrays would be something like:

verts =   [v0, v1, v2,  v2, v3, v0]
normals = [n0, n0, n0,  n0, n0, n0]
colors =  [c0, c0, c0,  c0, c0, c0]

Since a vertex and a normal are often 3 floats each, and a color is often 3 bytes, that gives, for each cube face, about:

verts   = 6 * 3 floats = 18 floats
normals = 6 * 3 floats = 18 floats
colors  = 6 * 3 bytes  = 18 bytes

= 36 floats and 18 bytes per cube face.

(I understand the number of bytes might change if different types are used, the exact figures are just for illustration.)

With indices, we can simplify this a little, giving:

verts   = [v0, v1, v2, v3]     (4 * 3 = 12 floats)
normals = [n0, n0, n0, n0]     (4 * 3 = 12 floats)
colors  = [c0, c0, c0, c0]     (4 * 3 = 12 bytes)
indices = [0, 1, 2,  2, 3, 0]  (6 shorts)

= 24 floats + 12 bytes, and maybe 6 shorts, per cube face.

See how in the latter case, vertices 0 and 2 are used twice, but only represented once in each of the verts, normals and colors arrays. This sounds like a small win for using indices, even in the extreme case of every single geometry edge being a seam.

This leads me to conclude that:

3. When using GL_TRIANGLES, one should always use indexed arrays, even for geometry which is all seams.

Please correct my conclusions in bold if they are wrong.

解决方案

From this I conclude that when rendering geometry which is all seams or mostly seams, when using GL_TRIANGLE_STRIP or _FAN, then I should never use indexed arrays, and should instead always use gl[Multi]DrawArrays.

No, and the reason is quite simple.

Your conclusion is based on the fact you have analysed a single quad composed by two triangles. These two triangles drawn using triangle fan/strip cannot be simplified using indexed arrays.

But try to think about a large terrain geometry. Each terrain block is drawn as a quad, using triangle fan/strip primitive. For example:

Each triangle strip in the figure has in common all vertices with adjacent triangle strips, and using indices allow to compress the geometry definition, instead of repeating vertices for each triangle strip.


Basically, drawing primitives (triangles, fans and strips) using indices are usefull whenever you can share most of vertices of a single primitive with another one.

Sharing the information allow to save information transmission bandwidth, but it is not the only advantage. Actually indexed arrays allow:

  • Avoid the synchronization of the information belonging to the same "conceptual" vertex, specified many times
  • Allow to perform the same shader operation on a single vertex instead executing many times, one for each vertex duplication.
  • Furthermore, combining the use of triangle strips/fans and indices allow the application to compress the indices buffer, since the strip/fan specification requires less indices (a triangle requires always 3 indices for each face).

Indexed array cannot be used, as you have specified, whenever a vertex cannot share every information associated with it (color, texture coords and so on) with another coincident vertex.


Just for the sake of completeness, the size of the information necessary for the geometry specification is not the only factor wich determine the optimal rendering operation.

Infact, another fundamental factor for primitive rendering is the cache localization of the data. Badly specified geometry data (non interleaved buffer objects, long triangle strips...) causes a lot of cache misses, degrading graphic card performance.

In order to optimize the rendering operation, the vertex specification shall be reordered in a way to reuse previously specified vertices, with the most probability. In such way, the graphic card cache line can reuse previously specified vertices without fetching them from memory.

这篇关于什么时候应该使用OpenGL的顶点索引数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆