好的,所以我在纯javascript中制作3D渲染引擎,当然是挑战 - 测试我的线性代数技能。我没有使用webgl,所以请不要说"使用webgl"。
无论如何,软件将采用三角形,相机和局部变换,并将数据渲染到屏幕上(我甚至将其设为交互式)
然而,只有6行渲染代码:
// some shading and math calculations then this:
context.fillStyle = color;
context.strokeStyle = color;
context.beginPath();
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.lineTo(x2, y2);
context.lineTo(x0, y0);
context.closePath();
context.fill();
context.stroke();
虽然可行,但我的Chromebook上的4k +面孔下降到10fps。 (常规计算机上60fps)
无论如何,输出这个:
但为了让它更快,并且因为画布状态变化很慢,我删除了笔划,制作渲染代码:
// some shading and math calculations then this:
context.fillStyle = color;
//context.strokeStyle = color;
context.beginPath();
context.moveTo(x0, y0);
context.lineTo(x1, y1);
context.lineTo(x2, y2);
context.lineTo(x0, y0);
context.closePath();
context.fill();
//context.stroke();
的运行速度是原来的两倍,但是渲染到屏幕上的结果是:(不同型号)
在三角形的边缘到处都有丑陋的线条(当我重新添加笔划时会被删除)
然而,fps翻倍且性能提升很好......
所以我相信这些线是因为画布填充不包括它所描绘的区域(大纲,如你所说)。
我试图用数学来修复它,虽然它有效,但有些边缘情况并不是
所以我的问题如下: 有没有办法让上下文填充包括没有描边的描边区域,因为它非常昂贵?
答案 0 :(得分:3)
同时使用笔触和填充将强制光栅化两次,这解释了大概的双倍时间。
你在三角形之间出现毛刺的原因是因为舍入误差和抗锯齿。对此没有直接的解决方案;当然,笔划将覆盖毛刺,但如果没有笔划,则要求您至少偏移并扩展每个其他三角形。
然而,您可以使用一个小技巧来掩盖间隙,即在顶部偏移上重绘整个图像(作为位图)只需一个像素(您可能会使用0.5像素,但需要消除锯齿) )。这增加了时间,但远远小于光栅化或重新计算路径。
假设左边的结果是你所拥有的(在这里模拟)有明显的差距。如右图所示将其重新绘制在顶部将覆盖间隙,而不会有太多失真。
只需使用:
ctx.drawImage(sourceCanvas, 1, 1);
提示:当只调用fill()
时,您不需要closePath()
,因为它被称为隐式,保存一个操作。微观上的增益可能但仍然存在(更复杂的几何形状它甚至可能有影响:))。
注意:绘制到自身将导致临时位图副本的内部分配。但是,您只需要执行一次额外的drawImage()
操作。选项是使用非画布渲染,但两次绘制到主显示的画布。无论哪种方式......
var ctx = c.getContext("2d");
ctx.fillStyle = "#777";
tri(10,10, 72,17, 40.2, 100);
// simulates gap
ctx.fillStyle = "#222";
tri(72.5,17.5, 40.7,100.5, 90,25);
// fill entire image back again, drawn twice here for demo
ctx.drawImage(c, 100, 0);
ctx.drawImage(c, 0, 0, 100, 150, 101, 1, 100, 150);
ctx.fillText("Raster", 5, 8);
ctx.fillText("Offset self", 105, 8);
function tri(x0,y0,x1,y1,x2,y2) {
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.fill();
}
<canvas id=c></canvas>