登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
 内容搜索 网页 下载 源代码
热点文章
  SSE 介紹
  浮点数到整数的快速转换
  基于SSE指令集的程序设计简介
  CPU 的 cache 和 latency
  关键字 对齐 内存对齐
  INTEL 体系结构 MMX™ ..
  在非MFC程序中使用调试宏 AS..
  Microsoft Visual C++ 浮点优..
  INTEL X86 体系 32 位汇编语..
  加速&优化技术
  加快程序运行速度的技巧
  VC代码的编写和调试
本站原创
您现在的位置:立华软件园->游戏开发->程序设计->优化调试
加速&优化技术
发表日期:2006-08-28作者:[转贴] 出处:  

译者序:这是一篇讲解3D引擎中,某些细节优化的文章,文中使用的方法同样适用于其他场合。不过因为本人对这方面的技术和词汇不是很熟悉,所以这篇翻译可能存在很多谬误,希望大家多加批评指正。
原文:Speed-up & Optimization Techniques

绪论
  在这个页面,我收集了一些不同的加速3D引擎的小窍门。我会先介绍一些显而易见的,因为许多人会忽视它们,接着是一些更精彩的。如果你有其他的窍门和算法,尽可以告诉我。

Float --> int 转化
值得尝试的做法,因为这种转化一般会更慢。我知道的这两种方法是用#pragma和内联函数。首先,#pragma:

#pragma aux RoundToInt= "fistp DWORD [eax]" parm nomemory [eax] [8087] modify exact [8087];


这种方法表现的非常好,WDISASM 表明编译器抛弃了对__CHP的调用而内联了这个转化。另一种方法不使用#pragma,可以被移植到其他编译器。这由"InnerSect"提出:

#define FIST_MAGIC ((((65536.0 * 65536.0 * 16)+(65536.0 * 0.5))* 65536.0))
int32 QuickFist(float inval)
{
    double dtemp = FIST_MAGIC + inval;
    return ((*(int32 *)&dtemp) - 0x80000000);
}

他做了一些测试,说来有趣,如果我没记错的话,他发现上面的方法更快。


提前计算
  提前计算所有数据!你没法提前计算太多东西。不要以为什么都能查表,那样你会失去灵活性。关注不同的方法。首先要提前计算的是你的法向量。表面法向量和顶点法向量。对调试来说非常重要-这些向量的计算耗时惊人。一旦你提前计算了这些数值,你只要像对待对象的其他部分一样旋转他们就可以了。可是不要去平移或者缩放他们。它们必须保持为单位向量。如果你偶然缩放了他们,可以乘以一个相反的比例把他们还原;例如:

| Sx 0 0 0 |
Transform Matrix = | 0 Sy 0 0 |
| 0 0 Sz 0 |
| 0 0 0 0 |
然后你需要这样:
NormalX *= 1 / Sx
NormalY *= 1 / Sy
NormalZ *= 1 / Sz

当你进行裁减和计算光照的时候,你也不需要平移他们。Also you don't need to transform your normals when you perform culling or lighting. 简单的反向平移你考虑到的其他向量,避免矩阵/向量的乘法。你反向平移可以简单的通过重置上方3×3的矩阵来实现:

For every row
For every column
output[row][column] = input[column][row]
End
End

转换灯光,视角向量,以及任何依赖这个矩阵的向量,都因为提前计算而节省了大量工作。你只需要像往常一样计算,用新的向量和旧的法向量。


倒数
  如果你需要做很多次除数相同的除法,取除数的倒数,变成乘法。倒数就是1/n,n是你的除数。如果你确实很聪明,你会发现在运行 fdiv 的时候还有其他事可做。一个不错的窍门是预热高速缓存,高速缓存命中失败会导致从内存中载入数据等占用很多时间。所以,当你坐等fdiv完成的时候,为什么不读一些内存地址呢?那样它们就会被载入高速缓存了。 在我的屏幕渲染的代码里面,这样看起来运行良好。你可以把这个技术用在透视纹理映射上。也有助于你做透视转换。如果想还原那个倒数,再做一次1/n就可以了。非常精彩。如果你喜欢冒险,你可以把数据存储为倒数,例如Z。我还没试过-这会很难调试。


顶点标识
  任意给定一个需要处理的顶点列表,你会发现有很多-也就是说至少一半-是不可见的,在裁减区域之外。你需要快速排除它们。一个简单的方法就是给这些顶点加一个'可见'标志。

  进入处理循环之前,在准备期间,把这个标志设为false。然后,进入循环之后,如果发现顶点是必要的,就设为true。例如,你发现一个三角形可见,就把它所有的顶点可见标志都设为true。在那之后,你可以简单的跳过或者排除那些没有设这个标志的顶点。这对复杂模型非常有用,因为他们包含大量顶点。同样可以这样处理有很多不可见部分的很大的场景,跳过不必要的渲染。如果用于光照,那你必须得小心。如果你进行可见性裁减的时候,没有计算光照,你会发现在边缘的地方出现错误。你在寻找已定义数据和未定义数据的交界,这很费神。。。

  一种方法识用一个计数器来标识。方法很简单。初始化的时候,你把计数器设置为某个非法值,例如-1 (0xFFFFFFFF).。同时,你把帧计数器设置为0。然后在你处理对象的过程中,如果你发现一个面/顶点需要处理,你就把它的计数器设置为和帧计数器相等。反之,不作任何设置和清除。接着,当你实际处理的是时候,你把它和帧计数器对比,那些计数器值和当前帧计数器相等的顶点/面片会被使用,其他的则被跳过。这在大的数据集很方便,因为那种情况下,每帧都正确清除那个标志代价高昂。


指针
  指针非常方便。利用它们你能实现精巧的数据结构,就像链表,二叉树等等。你也可以利用它们快速寻址。比如说你有一个数组,每个元素都是27字节长。你可以把它们填充到32字节,利用移位来计算地址。但是,数组的每个元素都浪费了5个字节。这很浪费。因此,用指针来寻址。就是说你的顶点结构有27字节。在三角形结构中,不要用int vertindex[3],而是用vertex *vertptr[3]。然后简单的载入指针,寻址,就可以了。(译者注:说实话,这段话我没有完全理解,有不对的地方恳请读者指正)


三角形vs 多边形
  三角形易于处理,渲染速度快。但是如果你有一系列6边形构成的表面,你很容易把它们替换为多边形,不过对三角形渲染器来说,你得做6倍的工作。但是三角形渲染更快。个人推荐三角形,在基于三角形的环境操作起来很简单。多边形有它的优势,可能值得一试。如果有人拥有凸多边形偏移纹理的算法,我会非常感兴趣。


过度渲染/渲染不完全
  过度渲染是速度杀手。尤其是复合渲染代码。你绘制,再次绘制,二次重绘,三次重绘,等等。损失时间和速度。一个简单的排除过度渲染的方法是从前到后排列你的三角形,给它们提供Z-Buffer/S-Buffer。这仍然导致问题。完全依赖 Z-Buffer的三角形渲染会最终变成浪费时间。扫描所有的点,而不渲染任何东西!同样的复杂的分段插入S-Buffers代码,也要付出一定代价。 对大的三角形 S-Buffer看起来运作良好。但是,对大量小三角形,它就没那么吃香了;例如,我的S-buffer算法渲染一个不到3k三角形的头部模型,只计算lambert阴影,耗费了接近30秒钟。很明显,三角形数量使得分段插入的代码负载过大。我想,这里的解决方法是开发更高效的闭合和VSD算法。将来处理这个问题有很多可能性。

  另一个问题是“渲染不完全”(我的术语)。这是说,你花费了太多时间在处理离屏的多边形上。一些有帮助的因素是,场景中的可见多边形不会明显变化。到现在为止,你大概可以计算一个FPS中的可见多边形集了,用玩家的方向寻找一些需要注意的多边形,如果玩家靠的太近,就把它们变为临界点。有效范围例如包围球/包围盒在这里也能派上用场。Hierarchial模型也可能有帮助,用来决定哪部分模型是不必要的。


总结
这里有几条规则,可以让你的引擎跑得更快:

尽可能提前计算
不做不必要的计算
不要重复计算同一内容
如果可能,要利用以前计算的结果
寻找那些可以事半功倍的场合
在用汇编改写你的函数前,自问“我已经找到最好的解决方法了吗?”
试验!
冒险。
不要 重写任何代码仅仅因为“看起来慢”
探索你的目标构架,了解它的特性

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 加速&优化技术

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接

Copyright ©2001-2003 Allrights reserved
e_mail:站长:webmaster(at)lihuasoft.net
网站编程QQ群  
京ICP备05001064号

页面生成时间:0.00443