我目前正在开发一个手绘应用程序,需要支持多种背景纹理。例如,类似纸张的纹理或图像。两种背景纹理上的图形应具有相同的行为。
当使用一种或另一种纹理作为绘图的起点时,效果非常好,即将所有传入笔划直接与背景纹理混合。
但是,我想采取不同的方法:将所有笔划绘制到最初透明的层,然后将该层与选定的背景混合。 这样做的优点是图形是独立的,并且与背景分离。 例如,我可以将整个图形与不同的背景混合,而不必将所有笔划直接与此背景混合。
问题是:根据透明层的颜色,混合图像(背景+笔划层)的结果看起来完全不同。例如,使用 rgba 值,将透明层设置为透明白色(1,1,1,0)会产生比将层设置为透明黑色(0,0,0,0)更亮的颜色。这很有意义,因为我们必须将笔划与透明颜色混合。我基本上想要的是 “中性” 透明度此透明层上的笔划应仅与背景图像交互,而不与透明层交互。透明层只能用于存储绘制的笔划。
我的问题是:这有可能吗?我找不到解决这个问题的方法。问题是透明层(它只是一个具有透明颜色的纹理)必须有一个颜色,并且传入的笔划必须与该颜色混合。有没有办法避免这种情况?
我想出了办法:
对于混合两种透明颜色,可以使用波特-达夫算法。对其进行了描述 here 例如混合目标颜色和源颜色的方法如下:
inline float4 porter_duff_blending(float4 dest, float4 source) { float alpha = source.a; float inv_alpha = 1 - alpha; float blend_alpha = alpha + inv_alpha * dest.a; float4 blend_color = (1.0 / blend_alpha) * ((alpha * source) + (inv_alpha * dest.a * dest)); blend_color.a = blend_alpha; return blend_color; };
这允许在一个单独的透明层中绘制图形,该层可以应用于不同的背景。