HTML5 Canvas Creative Alpha-Blending

时间:2013-07-02 05:34:50

标签: javascript html5 canvas html5-canvas alphablending

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

That's what it looks like. Trust me, it's better when animated.

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

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

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

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

Later blue circle obscures earlier drawn ones.

Here's what the problem looks like in action. Notice the different appearance of the left side of the lump.

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

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

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

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

2 个答案:

答案 0 :(得分:3)

好的,谢谢你的帮助,伙计们。 :)但是,我明白,这是一个奇怪的问题,很难回答。

我将这部分放在这里,以便它将为未来的观众提供资源。我仍然对其他可能的解决方案很感兴趣,所以我希望其他人会在有任何想法的情况下发布答案。

无论如何,我自己想出了一个解决方案:在绘制圆圈之前,我对它们进行了comb sort以按z值排序,然后将它们反向绘制。结果是最高值的物体(应该更靠近观察者)最后绘制,因此不会被其他圆圈遮挡。结果是模糊效果仍然存在,但它现在以一种对几何有意义的方式发生。以下是此校正的模拟结果,请注意它现在是对称的:

Normal use Lump test

答案 1 :(得分:3)

如果您可以将您的圈子分解为两组(平均值和赔率),以便组内的圆圈之间没有重叠,则以下序列应该会产生预期的效果:

  1. 清除背景
  2. 使用1.0(不透明)
  3. 的alpha绘制平均值
  4. 使用1.0(不透明)
  5. 的alpha绘制赔率
  6. 以0.5
  7. 的alpha绘制平均值

    既不是平均也不是赔率的地方会显示背景。仅由evens覆盖的那些将显示100%不透明度的均匀。赔率覆盖的那些将显示100%不透明度的几率。两者所涵盖的将显示50%的混合。

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

    顺便提一下,如果混合模式是固定的,那么可以通过在单独的画布上绘制平均值和几率而不是圆形,而是作为不透明的矩形,并从其中一个的alpha通道中减去,来极大地加速渲染。画出一个固定的" cookie-cutter"帆布或填充图案。如果正确计算饼干切割画布的内容,这种方法可用于两组以上的画布。确定千篇一律画布的内容可能有点慢,但只需要做一次。