实时阴影绘制技术研究

C++博客 首页 新随笔 联系 聚合 管理
  48 Posts :: 20 Stories :: 57 Comments :: 0 Trackbacks
作者:azure
转自:http://www.azure.com.cn/article.asp?id=192

通常影响程序运行速度的地方,都是在执行次数最多的地方。比如显示一张800*600的256色图形,如果在设置调色板时浪费了0.001秒,那么对整个程序不会有很大影响,因为设置调色板的操作只要作一次就完成,但是每绘出一点要多浪费0.001秒,那么整张图画完就会慢上800*600*0.001秒,这是一个相当可观的数目。下面介绍一些常用的技巧。

一.尽量使用整数,少用浮点数
  整数运算比浮点数快得多,而在绘图程序中用到小数点的机会实在少之又少,所以这是很容易做到的技巧。

二.避免乘法与除法
  乘法与除法都是相当浪费CPU运算时间的一种运算,所以在绘图程序中应尽量避免,在无法避免时,如果乘除的数目为2次方,例如2、4、8、16等,则可改用左移或右移来取代:

a*2^n-->a<<n 例:a*16-->a<<4
a/2^n-->a>>n 例:a/32-->a>>5

  上式中2^n表示2的n次方。

三.少用求模运算
  求模的运算(%)通常也是用乘除来完成的,所以速度很慢,我们也要尽量避免,当然如果除数为2的次方,那么可以改用&来替代:

a%2^n --> a&(2^n-1)

例:a%8 --> a&0x07


注意,如果除数不是2的次方,绝不能用&来替代。

四.复杂的二维计算改用查表法
  所谓查表法,就是事先将一些运算结果存入表格中,然后在需要时直接取出来使用而不必再做运算。最常见的例子就是在做图形旋转时,往往会用到sin()、cos()等函数来计算角度,如果能将这些运算结果事先存于表格中,那么必能省下相当多的时间。
  对于较简单的显示图形的程序,我们也可以利用查表法来避免乘法的使用。例如在320*200*256模式下,我们要在(x,y)的地方画出一点,那么必然要做(y*320+x)的计算,如果能将每一条起始扫描线的位置事先算出并存入表格中:

unsinged table[200];
for( i=0; i<200; i++ )
table[i] = i * 320;

那么在绘点时便可以直接使用下面的方法来取得位置:

table[y] + x;

避免了乘法运算,这就是“以空间换取时间“的做法。还有一种变形的查表法也值得一提,那就是如果在程序中有很多地方都用到了相同的运算,那么可以事先算出结果并加以储存,例如:

......
MaxSize = width * height * 3 + 200;
......
MinSize = width * height * 3 - 100;
......

则可先算出size:

size = width * height * 3;
......
MaxSize = size + 200;
......
MinSize = size - 100;
......

五.将耗时的运算移到循环之外
  通常在循环内的程序码会执行较多次,所以应减少耗时的运算,例如320*200*256模式政绘制一个实心的矩形时:

char far *vp = (char far *)0xA0000000L;
for( y=50; y<150; y++ )
for( x=100; x<200; x++ )
*(vp+y*320+x) = 0x0f;

可以改成:

char far *vp = (char far *)0xA0000000L;
char far *p;
for( y=50; y<150; y++ )
{
p = vp+y*320+100; /* 将乘法移出内层循环*/
for( x=100; x<200; x++ )
*(p++) = 0x0f;
}

再进一步还可以更上一层楼,将乘法完全移出循环:

char far *vp = (char far *)0xA0000000L;
char far *p;
int offset = 320-(200-100);
p = vp+50*320+100;
for( y=50; y<150; y++ )
{
for( x=100; x<200; x++ )
*(p++) = 0x0f;
p += offset;
}

其中offset的值正是矩形中最右边的一点到下一条扫描线最左边一点的差距值。

六.使用寄存器变量
  寄存器的存取速度要比内存快,一般c/c++编译器都至少提供1~2个寄存器变量给程序使用,我们应该将使用最频繁的变量定义成寄存器变量,这样可以加快执行效率,例如:

register int i;
for( i=0; i<3000; i++ )
*(p+i) = 0x0f;

七.编译器的设置
  在编译程序时,我们也可以通过某些设置来加快程序效率,例如,产生最快的执行速度的最佳化,不做堆栈溢出检查等,如果你使用tc20,那么只要在Option菜单中选Compiler/Optimizations,然后选择底部的Fastest Code按钮便可。读者可以自行参考相关手册。
posted on 2006-03-17 23:27 苦行僧 阅读(653) 评论(0)  编辑 收藏 引用 所属分类: 转载

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理