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

Javascript 为软件渲染器实现z缓冲的最快方法?,javascript,html5-canvas,zbuffer,scanline,Javascript,Html5 Canvas,Zbuffer,Scanline,我正在实现一个javascript软件渲染器(出于学术目的)。它处理将三维对象表示为三角形的操作,并处理从三维空间到二维空间的透视投影 到目前为止,我使用lineTo和fillRect来表示屏幕上的顶点和线条。我甚至使用了lineTo来进行扫描线三角形填充。(您可以签出该项目) 到目前为止,FPS已经相当不错了。但作业的最后一部分是实现z缓冲:P。据我所知,唯一的方法是停止使用lineTo填充三角形,并用1px线数组或1px正方形数组填充它们。(因为在绘制每个“像素”之前,我必须检查深度缓冲区,

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

到目前为止,我使用
lineTo
fillRect
来表示屏幕上的顶点和线条。我甚至使用了
lineTo
来进行扫描线三角形填充。(您可以签出该项目)

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

问题是,用微小的矩形或直线填充三角形的速度很慢。把所有东西都降到2磅。所以我的问题是,有没有办法画一个像素而不是一条很小的线(可能更快)

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

干杯

[编辑]在等待回答时,我将修改三角形填充函数,以绘制4px大小的“像素”,而不是1px。但这看起来很糟糕…

看看这个:

//点0,1,2,3正面
var fAvgZ=(cube.processPoints[0].colorZ+
cube.processPoints[1].colorZ+
cube.processPoints[2].colorZ+
cube.processPoints[3].colorZ)/4/20;
//顶部0,2,4,6点
var tAvgZ=(cube.processPoints[0].colorZ+
cube.processPoints[2].colorZ+
cube.processPoints[4].colorZ+
cube.processPoints[6].colorZ)/4/20;
//点4,5,6,7后方
var reAvgZ=(cube.processPoints[4].colorZ+
cube.processPoints[5].colorZ+
cube.processPoints[6].colorZ+
cube.processPoints[7].colorZ)/4/20;
//第1,3,5,7点底部
var bAvgZ=(cube.processPoints[1].colorZ+
cube.processPoints[3].colorZ+
cube.processPoints[5].colorZ+
cube.processPoints[7].colorZ)/4/20;
//点2,3,6,7右侧
var rAvgZ=(cube.processPoints[2].colorZ+
cube.processPoints[3].colorZ+
cube.processPoints[6].colorZ+
cube.processPoints[7].colorZ)/4/20;
//左侧0,1,4,5点
var lAvgZ=(cube.processPoints[0].colorZ+
cube.processPoints[1].colorZ+
cube.processPoints[4].colorZ+
cube.processPoints[5].colorZ)/4/20;
变量层=[{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},
{键:10,val:lAvgZ},
{key:11,val:lAvgZ}];
var-explay=layers.sort(函数(a,b){
返回(a.val-b.val);
});
对于(变量i=0;i
这绝不是对点值进行平均/排序的最有效方法,而且可能只需使用多维数据集预先存在的属性编写较少的代码行即可完成,但基本概念保持不变

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

这可以简化为:

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);
});
var层=[];
对于(变量i=0;i
似乎确实有一些附带案例存在快速订购问题

这似乎更准确:

var层=[];
对于(变量i=0;i<12;++i){
var side1=立方体边[i];
var side2=立方体边[++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+
processPoints[side2.c].colorZ)/6;
推送({key:i-1,val:avg});
layers.push({key:i,val:avg});
}
var-explay=layers.sort(函数(a,b){
返回(a.val-b.val);
});

您应该只需要跟踪每个多边形/三角形的深度,并从最远到最近进行渲染(画家的算法)。我认为每个点的平均深度应该足以确定绘制的顺序。@shmiddy我知道画家的算法。但任务并不是这样。画家的alg也不能这样做:不,但是对于简单的多面体,它就足够了。快速提问,为什么不使用内置画布绘制工具填充三角形的模式呢?JSFIDLE似乎因为资源链接不再可用而中断。
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);
});
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);
});