我正在编写一个 3D 图形库,作为我项目的一部分,我现在一切正常,但还不够好。
特别是,我的主要头痛是我的像素填充率非常慢 - 在我的目标机器上绘制一个跨越 800x600 窗口一半的三角形时,我什至无法管理 30 FPS(这无疑是一台较旧的计算机,但它应该能够管理这个...... )
我在我的可执行文件上运行了 gprof,最后得到了以下有趣的行:
% cumulative self self total
time seconds seconds calls ms/call ms/call name
43.51 9.50 9.50 vSwap
34.86 17.11 7.61 179944 0.04 0.04 grInterpolateHLine
13.99 20.17 3.06 grClearDepthBuffer
<snip>
0.76 21.78 0.17 624 0.27 12.46 grScanlineFill
该函数vSwap
是我的双缓冲区交换函数,它还执行 vsyching,所以对我来说,测试程序将花费大量时间在那里等待是有意义的。grScanlineFill
是我的三角形绘制函数,它创建一个边列表,然后调用grInterpolateHLine
实际填充三角形。
我的引擎目前正在使用 Z 缓冲区来执行隐藏表面移除。如果我们忽略(假定的)vsync 开销,那么测试程序会花费大约 85% 的执行时间来清除深度缓冲区,或者根据深度缓冲区中的值写入像素。我的深度缓冲区清除功能本身很简单:将浮点数的最大值复制到每个元素中。功能grInterpolateHLine
是:
void grInterpolateHLine(int x1, int x2, int y, float z, float zstep, int colour) {
for(; x1 <= x2; x1 ++, z += zstep) {
if(z < grDepthBuffer[x1 + y*VIDEO_WIDTH]) {
vSetPixel(x1, y, colour);
grDepthBuffer[x1 + y*VIDEO_WIDTH] = z;
}
}
}
我真的不知道如何改进它,特别是考虑到这vSetPixel
是一个宏。
我对优化的全部想法已经缩减为一个:
- 使用整数/定点深度缓冲区。
整数/定点深度缓冲区的问题是插值可能非常烦人,而且我实际上还没有定点数库。有什么进一步的想法吗?任何建议将不胜感激。