为软件渲染器实现z缓冲的最快方法?

时间:2012-10-01 16:24:34

标签: javascript html5-canvas zbuffer scanline

我正在实施一个javascript软件渲染器(用于学术目的)。它将3d对象表示为三角形,并处理从三维空间到二维空间的透视投影。

到目前为止,我使用lineTofillRect来表示屏幕上的顶点和线条。我甚至用lineTo来做扫描线三角形填充。 (您可以查看项目here

到目前为止,FPS一直很好。但是,分配的最后一部分是实现z-Buffering:P。据我所知,唯一的方法是使用lineTo停止填充我的三角形,并用1px行数组或1px正方形数组填充它们。 (因为在我绘制每个“像素”之前,我必须检查深度缓冲区,看看我是否应该实际绘制它。)

问题是,用微小的矩形或线条填充三角形是慢的。将所有内容降至2FPS。所以我的问题是,是否有任何方法可以绘制一个像素而不是一条细线(可能更快)?

或者,我还能做些什么来加快速度?我的目标是让它足够快地旋转以演示原理。 (6-10fps就足够了)

干杯。

[编辑]当我等待答案时,我将继续修改我的三角形填充函数以绘制4px大小的“像素”而不是1px。但这看起来很麻烦......

1 个答案:

答案 0 :(得分:2)

检查出来:http://jsfiddle.net/ZXjAM/2/

// points 0,1,2,3 front face
var fAvgZ = (cube.processPoints[0].colorZ + 
    cube.processPoints[1].colorZ + 
    cube.processPoints[2].colorZ + 
    cube.processPoints[3].colorZ) / 4 / 20;

// points 0,2,4,6 top
var tAvgZ = (cube.processPoints[0].colorZ + 
    cube.processPoints[2].colorZ + 
    cube.processPoints[4].colorZ + 
    cube.processPoints[6].colorZ) / 4 / 20;

// points 4,5,6,7 rear
var reAvgZ = (cube.processPoints[4].colorZ + 
    cube.processPoints[5].colorZ + 
    cube.processPoints[6].colorZ + 
    cube.processPoints[7].colorZ) / 4 / 20;

// points 1,3,5,7 bottom
var bAvgZ = (cube.processPoints[1].colorZ + 
    cube.processPoints[3].colorZ + 
    cube.processPoints[5].colorZ + 
    cube.processPoints[7].colorZ) / 4 / 20;

// points 2,3,6,7 right side
var rAvgZ = (cube.processPoints[2].colorZ + 
    cube.processPoints[3].colorZ + 
    cube.processPoints[6].colorZ + 
    cube.processPoints[7].colorZ) / 4 / 20;

// points 0,1,4,5 left side
var lAvgZ = (cube.processPoints[0].colorZ + 
    cube.processPoints[1].colorZ + 
    cube.processPoints[4].colorZ + 
    cube.processPoints[5].colorZ) / 4 / 20;

var layers = [{key:0, val:fAvgZ},
          {key:1, val:fAvgZ},
          {key:2, val:tAvgZ},
          {key:3, val:tAvgZ},
          {key:4, val:reAvgZ},
          {key:5, val:reAvgZ},
          {key:6, val:bAvgZ},
          {key:7, val:bAvgZ},
          {key:8, val:rAvgZ},
          {key:9, val:rAvgZ},
          {key:10, val:lAvgZ},
          {key:11, val:lAvgZ}];

var outLay = layers.sort(function(a,b){
    return (a.val - b.val);
});

for(var i = 0; i < outLay.length; i++)
{
    var k = outLay[i].key;
    ...
}

这绝不是对点值进行平均/排序的最有效方法,并且可以使用多维数据集的预先存在的属性以较少的代码行完成,但基本概念保持不变。 / p>

我找到了平均z-index并使用它来假设分层顺序。显然,这对所有事情都不适用,但对于简单的多面体,它应该足够了。

这可以简化为:

var layers = [];
for (var i = 0; i < cube.sides.length; i++){
    var side = cube.sides[i];
    var avg = (cube.processPoints[side.a].colorZ + 
               cube.processPoints[side.b].colorZ + 
               cube.processPoints[side.c].colorZ) / 3 / 20;                   
    layers.push({key:i, val:avg});
}

var outLay = layers.sort(function(a,b){
    return (a.val - b.val);
});

似乎有一些边缘情况存在快速订购问题。

这似乎更准确:http://jsfiddle.net/ZXjAM/4/

var layers = [];
for (var i = 0; i < 12; ++i){
    var side1 = cube.sides[i];
    var side2 = cube.sides[++i];
    var avg = (cube.processPoints[side1.a].colorZ + 
               cube.processPoints[side1.b].colorZ + 
               cube.processPoints[side1.c].colorZ + 
               cube.processPoints[side2.a].colorZ + 
               cube.processPoints[side2.b].colorZ + 
               cube.processPoints[side2.c].colorZ) / 6;                   
    layers.push({key:i-1, val:avg});
    layers.push({key:i, val:avg});
}

var outLay = layers.sort(function(a,b){
    return (a.val - b.val);
});