HTML5 Canvas Creative Alpha-Blending

min*_*tea 6 javascript html5 canvas alphablending html5-canvas

所以我有一个动画,我用javascript和HTML5编码(没有库,没有插件,没有任何东西,我希望它保持这种方式).动画使用物理(基本上是一堆附着在质量上的不寻常弹簧)来模拟一种简单的液体.程序的这一部分的输出是对象的网格(2d阵列),每个对象具有az值.这很好用.将数据绘制到HTML5 Canvas时出现问题.

这就是它的样子. 相信我,动画时更好.

这就是它的样子.相信我,动画时更好.

对于每个数据点,程序绘制一个圆圈,其颜色由z值确定.然而,仅仅绘制这些点,网格图案非常明显,很难看到它代表的流体.为了解决这个问题,我使圆圈更大,更透明,使它们相互重叠,混合颜色,形成简单的卷积模糊.结果既快又美,但对于一个小缺陷:

当圆圈按顺序绘制时,它们的颜色值不会平均堆叠,因此后面绘制的圆圈会遮挡先前绘制的圆圈.在数学上,渲染器正在重复加权平均值的圆的颜色值.这适用于两个圆圈,每个圆圈的值为0.5*alpha_n,但对于三个圆圈,渲染器采用最新圆圈的平均值与其他两个圆圈的平均值,给最新圆圈的值为0.5*alpha_n,但较早的圆圈每个值为0.25*alpha_n.随着越来越多的圈子重叠,这个过程将继续进行,从而对较新的圈子和较旧的圈子产生偏见.相反,我想要的是三个或更多个圆圈中的每个圆圈都得到0.33*alpha_n的值,这样早期的圆圈就不会被遮挡.

这是阿尔法混合的图像.请注意,后面的蓝色圆圈模糊了之前绘制的红色和绿色圆圈:

后来的蓝色圆圈掩盖了之前绘制的那些.

这就是问题在行动中的样子. 注意肿块左侧的不同外观.

这就是问题在行动中的样子.注意肿块左侧的不同外观.

为了解决这个问题,我尝试了各种方法:

  • 使用不同的画布"混合模式"."乘法"(如上图所示)完成了这一伎俩,但却造成了不幸的色彩扭曲.
  • 集体绘制电话.我没有将每个圆圈作为一个单独的画布路径,而是试图将它们拼凑成一个.不幸的是,这与单独的填充颜色不相容,而且,路径根本没有与自身融合,创造出哑光,单调的轮廓.
  • 隔行扫描绘图顺序.我没有按照0到n的顺序绘制圆圈,而是尝试首先绘制平均值,然后绘制赔率.这只是部分地解决了这个问题,并且创造了一个难看的分层模式,其中赔率似乎漂浮在平均值之上.
  • 使用putImageData构建我自己的混合模式.我尝试使用javascript创建一个手动像素着色器以满足我的需求,但是,正如预期的那样,它太慢了.

在这一点上,我有点卡住了.我正在寻找创造性的方法来解决或绕过这个问题,我欢迎你的想法.我不是很有兴趣被告知这是不可能的,因为我可以为自己解决这个问题.您如何从这些数据点中优雅地绘制流体?

sup*_*cat 4

如果您可以将圆圈分解为两组(偶数和奇数),使得组内的圆圈之间没有重叠,则以下顺序应该会产生所需的效果:

  1. 清除背景
  2. 使用 1.0 的 alpha 绘制偶数(不透明)
  3. 使用 alpha 1.0 绘制赔率(不透明)
  4. 绘制 alpha 为 0.5 的偶数

既没有被偶数也没有被奇数覆盖的地方将显示背景。那些仅被事件覆盖的事件将以 100% 不透明度显示事件。赔率覆盖的赔率将以100%不透明度显示。两者覆盖的内容将显示 50% 的混合。

还有其他方法可以用来尝试混合三组或更多组对象,但“精确”地做到这一点很复杂。如果有三个或更多图像应根据其 Alpha 通道均匀混合,另一种方法是在全局 Alpha 从 1 衰减到 0 的同时重复绘制所有图像(请注意,上述过程实际上是这样做的,但它在数字上是这样的)当只有两个图像时精确)。数字舍入问题限制了该技术的精度,但即使进行两遍或三遍也可以大大降低排序引起的视觉伪影的严重性,同时使用比精确混合所需的步骤更少的步骤。

顺便说一句,如果混合模式是固定的,则可以通过在单独的画布上绘制偶数和奇数而不是圆形而是不透明矩形,并从其中一个画布的 Alpha 通道中减去内容来极大地加快渲染速度固定的“千篇一律”画布或填充图案。如果正确计算千篇一律的画布的内容,这种方法可以用于两组以上的画布。确定千篇一律的画布的内容可能会有点慢,但只需要完成一次。