绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
在 WPF 中实现融合效果
2022-09-27 16:55:39

1. 融合效果#

融合效果是指对两个接近的元素进行高斯模糊后再提高对比度,使它们看上去“粘”在一起。在之前的一篇文章中,我使用 Win2D 实现了融合效果,效果如下:

不过 Win2D 不适用于 WPF,在 WPF 中可以使用 BlurEffect 配合自定义 Effect 实现类似的效果。HandyControl 中有一个使用自定义的 ContrastEffect 实现融合效果的 Demo,如下图:

但是 ContrastEffect 是通过 Contrast 属性同时控制 RGBA 四个通道的对比值,所以没办法控制准确地颜色。另外 HandyControl 也提供了 ColorMatrixEffect,不过 ColorMatrixEffect 很难控制对比度。
既然都用到自定义 Effect 了,这次索性自己写一个。

2. 自定义 Effect#

在 Win2D 中,实现融合效果的步骤是先使用 GaussianBlurEffect 在两个元素间产生粘连在一起的半透明像素,再用 ColorMatrixEffect 加强对比对,使半透明的像素变得完全不透明。

在 WPF 中我们可以直接使用自带的 BlurEffect 实现高斯模糊,效果如下:

接下来需要加强对比度。WPF 中没有 ColorMatrixEffect 的替代品,不过我们可以使用 HLSL(着色器语言)编写 PixelShader 并生成自定义的 WPF Effect。编写 PixelShader 可以使用 Shazzam Shader Editor, walterlv 有一篇关于如何使用这款编辑器的教程:

WPF 像素着色器入门:使用 Shazzam Shader Editor 编写 HLSL 像素着色器代码

在这里我编写了一个对 Alpha 进行二值化处理的 PixelShader 实现加强对比度功能,它的作用很简单:当像素的 Alpha 大于阈值就将 Alpha 置为 1,否则为 0,代码如下:

Copy
float Thresh : register(C0); float4 main(float2 uv : TEXCOORD) : COLOR { float4 color; color = tex2D(input, uv.xy); if (color.a == || color.a == 1 || Thresh == ) { return color; } float4 resultColor = ; float opacity = color.a > Thresh ? 1 : ; if (opacity > ) { resultColor.rgb = color.rgb / color.a * opacity; } resultColor.a = opacity; return resultColor; }

虽然确实实现了融合效果,但是圆形的边缘有严重的锯齿。很明显,问题出在上面的代码中 Alpha 通道终不是 0 就是 1,为了使边缘平滑,应该留下一些“中间派”。修改后的代码引用了 LowerThresh 和 UpperThresh,处于这两个阈值之间的像素用作保持边缘平滑的“中间派”,具体代码如下:

Copy
float UpperThresh : register(C0); float LowerThresh : register(C1); float4 main(float2 uv : TEXCOORD) : COLOR { float4 color; color = tex2D(input, uv.xy); if (color.a == || color.a == 1 || LowerThresh == ) { return color; } if (UpperThresh < LowerThresh) { return color; } float4 resultColor = ; float opacity = 1; if (color.a < LowerThresh) { opacity = ; } if (color.a > LowerThresh && color.a < UpperThresh) { opacity = (color.a - LowerThresh) / (UpperThresh - LowerThresh); } if (opacity > ) { resultColor.rgb = color.rgb / color.a * opacity; } resultColor.a = opacity; return resultColor; }

3. 后#

这篇文章介绍了如何使用自定义 Effect 实现融合效果,只要理解了融合效果的原理并动手实现了一次,之后就可以参考博客园的 ChokCoco 大佬玩出更多花样,例如这种效果::

更多好玩的效果可以参考 ChokCoco 大佬的博客:你所不知道的 CSS 滤镜技巧与细节

源码:https://github.com/DinoChan/wpf_design_and_animation_lab

分享好友

分享这个小栈给你的朋友们,一起进步吧。

.NET中大型研发必备
创建时间:2022-04-09 00:21:16
本系列文章适合有初/.NET知识的同学阅读(请在电脑上打开页面,获取更好的阅读效果)。 (1)本系列文章,旨在讲述研发一个中大型项目所需要了解的一系列“基本构件”,并提供这些“基本构件”在全网的【简单】、【快速】使用方法!!(并不深究技术原理) (2)通过阅读本系列文章,能让你在“正规”项目研发方面快速入门+进阶,并能达成“小团队构建大网站”的目的。 (3)本系列文章采用的技术,已成功应用到人工智能、产业互联网、社区电商、游戏、金融风控、智慧医疗、等项目上。
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • 红色侦察兵
    栈主

小栈成员

查看更多
  • miemieMIA
  • LCR_
  • xsy028
  • ?时光与海?
戳我,来吐槽~