繁体   English   中英

使画布填充包括形状中的笔划

[英]Make canvas fill include stroke in shapes

好的,所以我在纯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)

无论如何,这输出:

* Dragon渲染3D *

但为了使它更快,并且因为画布状态更改很慢,我删除了笔划,使得渲染代码:

// 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.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> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM