在 WPF 中實現融合效果

1. 融合效果融合效果是指對兩個接近的元素進行高斯模糊后再提高對比度,使它們看上去“粘”在一起 。在之前的一篇文章中 , 我使用 Win2D 實現了融合效果,效果如下:

在 WPF 中實現融合效果

文章插圖
不過 Win2D 不適用于 WPF,在 WPF 中可以使用 BlurEffect 配合自定義 Effect 實現類似的效果 。HandyControl 中有一個使用自定義的 ContrastEffect 實現融合效果的 Demo,如下圖:
在 WPF 中實現融合效果

文章插圖
但是 ContrastEffect 是通過 Contrast 屬性同時控制 RGBA 四個通道的對比值 , 所以沒辦法控制準確地顏色 。另外 HandyControl 也提供了 ColorMatrixEffect , 不過 ColorMatrixEffect 很難控制對比度 。既然都用到自定義 Effect 了 , 這次索性自己寫一個 。
2. 自定義 Effect在 Win2D 中,實現融合效果的步驟是先使用 GaussianBlurEffect 在兩個元素間產生粘連在一起的半透明像素,再用 ColorMatrixEffect 加強對比對,使半透明的像素變得完全不透明 。
在 WPF 中我們可以直接使用自帶的 BlurEffect 實現高斯模糊,效果如下:
在 WPF 中實現融合效果

文章插圖
接下來需要加強對比度 。WPF 中沒有 ColorMatrixEffect 的替代品,不過我們可以使用 HLSL(高級著色器語言)編寫 PixelShader 并生成自定義的 WPF Effect 。編寫 PixelShader 可以使用 Shazzam Shader Editor , walterlv 有一篇關于如何使用這款編輯器的教程:
WPF 像素著色器入門:使用 Shazzam Shader Editor 編寫 HLSL 像素著色器代碼
在這里我編寫了一個對 Alpha 進行二值化處理的 PixelShader 實現加強對比度功能,它的作用很簡單:當像素的 Alpha 大于閾值就將 Alpha 置為 1,否則為 0,代碼如下:
float Thresh : register(C0);float4 main(float2 uv : TEXCOORD) : COLOR{float4 color;color = tex2D(input, uv.xy);if (color.a == 0 || color.a == 1 || Thresh == 0){return color;}float4 resultColor = 0;float opacity = color.a > Thresh ? 1 : 0;if (opacity > 0){resultColor.rgb = color.rgb / color.a * opacity;}resultColor.a = opacity;return resultColor;}
在 WPF 中實現融合效果

文章插圖
雖然確實實現了融合效果 , 但是圓形的邊緣有嚴重的鋸齒 。很明顯,問題出在上面的代碼中 Alpha 通道最終不是 0 就是 1,為了使邊緣平滑 , 應該留下一些“中間派” 。修改后的代碼引用了 LowerThresh 和 UpperThresh,處于這兩個閾值之間的像素用作保持邊緣平滑的“中間派” , 具體代碼如下:
float UpperThresh : register(C0);float LowerThresh : register(C1);float4 main(float2 uv : TEXCOORD) : COLOR{float4 color;color = tex2D(input, uv.xy);if (color.a == 0 || color.a == 1 || LowerThresh == 0){return color;}if (UpperThresh < LowerThresh){return color;}float4 resultColor = 0;float opacity = 1;if (color.a < LowerThresh){opacity = 0;}if (color.a > LowerThresh && color.a < UpperThresh){opacity = (color.a - LowerThresh) / (UpperThresh - LowerThresh);}if (opacity > 0){resultColor.rgb = color.rgb / color.a * opacity;}resultColor.a = opacity;return resultColor;}
在 WPF 中實現融合效果

文章插圖
3. 最后這篇文章介紹了如何使用自定義 Effect 實現融合效果,只要理解了融合效果的原理并動手實現了一次,之后就可以參考博客園的 ChokCoco 大佬玩出更多花樣,例如這種效果::
【在 WPF 中實現融合效果】
在 WPF 中實現融合效果

文章插圖
更多好玩的效果可以參考 ChokCoco 大佬的博客:你所不知道的 CSS 濾鏡技巧與細節
源碼:https://github.com/DinoChan/wpf_design_and_animation_lab

    推薦閱讀