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类型。
#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中的使用,其他引擎中的用法,大同小异
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%,效果还是非常明显的。
在这里为了方便,我们使用的是在线优化方式(模型数据加载进内存后再优化)。而实际开发中,往往多使用离线优化,预先处理好模型数据,然后直接调用渲染就可以了,这样没有缓存和时间限制,效果更好。
这个库是平台无关,也没有第三方依赖,可以很方便的集成到自己的工具中去。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。