nvtrisrip是NVIDIA提供的一个开源优化库,这个库可以将三角形顶点索引数组转换为三角形带索引数组。可以极大的提高渲染速度。
NVIDIA这个库的官方地址是:
http://www.nvidia.com/object/nvtristrip_library.html
不过这里代码不全也不够新,推荐从GitHub上下载:
https://github.com/turbulenz/NvTriStrip
下载完毕后,我们把下面文件夹中的源代码加入到项目中:
/NvTriStrip/include
/NvTriStrip/src
一共为6个文件
需要注意的是VertexCache类有个非常奇怪的设计,在.h和.cpp中同时有两套实现代码。这会导致重定义,我们可以把.h中的代码注释起来。另外还需要修改entries变量为unsign short类型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#ifndef VERTEX_CACHE_H
#define VERTEX_CACHE_H
#include <string.h>
class
VertexCache
{
public
:
VertexCache(
int
size);
// {
// numEntries = size;
//
// entries = new int[numEntries];
//
// for(int i = 0; i < numEntries; i++)
// entries[i] = -1;
// }
VertexCache();
// { VertexCache(16); }
~VertexCache();
// { delete[] entries; entries = 0; }
bool
InCache(
int
entry);
// {
// bool returnVal = false;
// for(int i = 0; i < numEntries; i++)
// {
// if(entries[i] == entry)
// {
// returnVal = true;
// break;
// }
// }
//
// return returnVal;
// }
int
AddEntry(
int
entry);
// {
// int removed;
//
// removed = entries[numEntries - 1];
//
// //push everything right one
// for(int i = numEntries - 2; i >= 0; i--)
// {
// entries[i + 1] = entries[i];
// }
//
// entries[0] = entry;
//
// return removed;
// }
void
Clear();
// {
// memset(entries, -1, sizeof(int) * numEntries);
// }
void
Copy(VertexCache* inVcache) ;
// {
// for(int i = 0; i < numEntries; i++)
// {
// inVcache->Set(i, entries[i]);
// }
// }
int
At(
int
index);
// { return entries[index]; }
void
Set(
int
index,
int
value);
// { entries[index] = value; }
private
:
// int *entries;
//此处修改为unsigned short
unsigned
short
*entries;
int
numEntries;
};
#endif
|
我们看一下在SIO2中的使用,其他引擎中的用法,大同小异
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
void
ObjMod::optimize_mesh(unsigned
int
mesh_index, unsigned
int
vertex_cache_size) {
ObjMesh *objmesh = &
this
->objmesh[ mesh_index ];
unsigned
int
i = 0,
s = 0;
unsigned
short
n_group = 0;
//设置顶点缓存大小,顶点缓存越大,优化时间越长,优化效果越好,但是成边界递减关系
if
( vertex_cache_size )
SetCacheSize( vertex_cache_size );
while
( i != objmesh->n_objtrianglelist )
{
PrimitiveGroup *primitivegroup;
//通过三角形索引创建
//四个参数依次:被优化的三角形索引数组,三角形索引元素数量,优化后的三角形带数组,优化后的三角形带元素个数
if
( GenerateStrips( objmesh->objtrianglelist[ i ].indice_array,
objmesh->objtrianglelist[ i ].n_indice_array,
&primitivegroup,
&n_group,
true
) )
{
if
( primitivegroup[ 0 ].numIndices < objmesh->objtrianglelist[ i ].n_indice_array )
{
objmesh->objtrianglelist[ i ].mode = GL_TRIANGLE_STRIP;
//渲染模式修改为三角形带
objmesh->objtrianglelist[ i ].n_indice_array = primitivegroup[ 0 ].numIndices;
//重置数据数量
//重新申请内存//
s = primitivegroup[ 0 ].numIndices *
sizeof
( unsigned
short
);
//这块使用realloc有点浪费空间,因为优化后的三角形带占用内存比原先的三角形索引要小
objmesh->objtrianglelist[ i ].indice_array = ( unsigned
short
* )
realloc
( objmesh->objtrianglelist[ i ].indice_array,
s );
//复制数据
memcpy
( &objmesh->objtrianglelist[ i ].indice_array[ 0 ],
&primitivegroup[ 0 ].indices[ 0 ],
s );
}
//删除优化后的临时数据
delete
[] primitivegroup;
}
++i;
}
}
|
我们这里调用库的函数有两个:
SetCacheSize为设置优化库使用的缓存大小并非越大越好。而是根据模型精细度来考量的。
GenerateStrips就是核心的三角形优化算法了。
然后保存输出的数据删掉临时数据即可。
下面是一个测试报告,画面数为4726个三角形的静态模型。重复绘制模型200次,在iPad mini2上面的结果是:
未开三角形带优化时的FPS:
开启三角形带优化之后的FPS:
FPS提高了70%,效果还是非常明显的。
在这里为了方便,我们使用的是在线优化方式(模型数据加载进内存后再优化)。而实际开发中,往往多使用离线优化,预先处理好模型数据,然后直接调用渲染就可以了,这样没有缓存和时间限制,效果更好。
这个库是平台无关,也没有第三方依赖,可以很方便的集成到自己的工具中去。
本文转自 老G 51CTO博客,原文链接:http://blog.51cto.com/goldlion/1539218,如需转载请自行联系原作者