为软件渲染器实现 z 缓冲的最快方法?
-
12-12-2019 - |
题
我正在实现一个 javascript 软件渲染器(用于学术目的)。它处理将 3d 对象表示为三角形,并处理从 3d 空间到 2d 空间的透视投影。
到目前为止,我使用的是 lineTo
和 fillRect
表示屏幕上的顶点和线条。我什至用过 lineTo
进行扫描线三角形填充。(你可以查看该项目 这里)
到目前为止,FPS 相当不错。但作业的最后一部分是实现 z 缓冲:P。据我所知,做到这一点的唯一方法是停止使用填充我的三角形 lineTo
并用 1px 线数组或 1px 正方形数组填充它们。(因为在绘制每个“像素”之前,我必须检查深度缓冲区,看看是否应该实际绘制它。)
问题是,用小矩形或线条填充三角形的速度很慢。将一切降低至 2FPS。所以我的问题是,有没有什么方法可以绘制一个像素而不是一条细线(这可能更快)?
或者,我还能做些什么来加快速度?我的目标是让它旋转得足够快来演示原理。(6-10fps就足够了)
干杯。
[编辑] 当我等待答案时,我将继续修改我的三角形填充函数以绘制 4px 大小的“像素”而不是 1px。但这样看起来会很锯齿...
解决方案
看一下这个: 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;
...
}
这绝不是对点值进行平均/排序的最有效方法,并且可能可以使用多维数据集的预先存在的属性用更少的代码行来完成,但基本概念保持不变。
我正在查找平均 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);
});
似乎确实有一些边缘案例存在快速订购问题。
这似乎更准确: 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);
});
不隶属于 StackOverflow