在 WPF 中实现融合效果
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,代码如下:
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;
}
虽然确实实现了融合效果,但是圆形的边缘有严重的锯齿。很明显,问题出在上面的代码中 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;
}
3. 最后
这篇文章介绍了如何使用自定义 Effect 实现融合效果,只要理解了融合效果的原理并动手实现了一次,之后就可以参考博客园的 ChokCoco 大佬玩出更多花样,例如这种效果::
更多好玩的效果可以参考 ChokCoco 大佬的博客:你所不知道的 CSS 滤镜技巧与细节
源码:https://github.com/DinoChan/wpf_design_and_animation_lab
在 WPF 中实现融合效果的更多相关文章
- WPF中制作立体效果的文字或LOGO图形(续)
原文:WPF中制作立体效果的文字或LOGO图形(续) 上篇"WPF中制作立体效果的文字或LOGO图形"(http://blog.csdn.net/johnsuna/archive/ ...
- WPF中制作立体效果的文字或LOGO图形
原文:WPF中制作立体效果的文字或LOGO图形 较久之前,我曾写过一篇:"WPF绘制党徽(立体效果,Cool) "的博文.有感兴趣的朋友来EMAIL问是怎么制作的?本文解决此类问题 ...
- 浅谈WPF中对控件的位图特效(WPF Bitmap Effects)
原文:浅谈WPF中对控件的位图特效(WPF Bitmap Effects) -------------------------------------------------------------- ...
- 使用 Win2D 实现融合效果
1. 融合效果 在 CSS 中有一种实现融合效果的技巧,使用模糊滤镜(blur)叠加对比度滤镜(contrast)使两个接近的元素看上去"粘"在一起,如下图所示: 博客园的 Cho ...
- 在WPF中使用PlaneProjection模拟动态3D效果
原文:在WPF中使用PlaneProjection模拟动态3D效果 虽然在WPF中也集成了3D呈现的功能,在简单的3D应用中,有时候并不需要真实光影的3D场景.毕竟使用3D引擎会消耗很多资源,有时候使 ...
- WPF中,如何将Vista Aero效果扩展到整个窗口
原文:WPF中,如何将Vista Aero效果扩展到整个窗口 WPF中,如何将Vista Aero效果扩展到整个窗口 ...
- WPF中利用RadialGradient模拟放大镜效果
原文:WPF中利用RadialGradient模拟放大镜效果 --------------------------------------------------------------------- ...
- WPF中ListBox滚动时的缓动效果
原文:WPF中ListBox滚动时的缓动效果 上周工作中遇到的问题: 常规的ListBox在滚动时总是一格格的移动,感觉上很生硬. 所以想要实现类似Flash中的那种缓动的效果,使ListBox滚动时 ...
- MVVM模式解析和在WPF中的实现(三)命令绑定
MVVM模式解析和在WPF中的实现(三) 命令绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
随机推荐
- 【FAQ】接入HMS Core推送服务,服务端下发消息常见错误码原因分析及解决方法
HMS Core推送服务支持开发者使用HTTPS协议接入Push服务端,可以从服务器发送下行消息给终端设备.这篇文章汇总了服务端下发消息最常见的6个错误码,并提供了原因分析和解决方法,有遇到类似问题的 ...
- 解决报错ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/run/mysqld/mysqld.pid (code
问题的由来 MySQL服务没有正常关机,是电脑没电后自动关机产生,记录一下排查过程 1.本以为是pid的问题,上网找了教程,解决不了,然后看日志看了网上各种说是数据库内存溢出 2021-03-12T1 ...
- 常用的函数式接口Function接口和常用的函数式接口Function接口默认方法andThen
常用的函数式接口Function接口 package com.yang.Test.FunctionStudy; import java.util.function.Function; /** * ja ...
- 清北学堂 2020 国庆J2考前综合强化 Day6
目录 1. 题目 T1 双色球计数 题目描述 Sol 炼金术 题目描述 Sol T3 地铁大亨 题目描述 Sol T4 结束的派对 题目描述 Sol 算法 - 分治 1. 分治 2. 二分 3. 倍增 ...
- Frame双向通信插件FrameDataTrans
FrameDataTrans教程 博客园 乳鸽菌 20220729 核心原理是使用postMessage发送数据,window.addEventListener("message" ...
- React报错之Property 'X' does not exist on type 'HTMLElement'
正文从这开始~ 总览 在React中,当我们试图访问类型为HTMLElement 的元素上不存在的属性时,就会发生Property 'X' does not exist on type 'HTMLEl ...
- Nginx 文件传输效率、实时、压缩配置指令
# sendfile 开启文件高效传输模式 # 默认值:off # 位置:http.servcer.location-- # 开启和不开启worker访问的文件发送到浏览器的过程不同. # 不开启的时 ...
- Java学习 (五)基础篇 数据类型
目录 数据类型 强类型语言 弱类型语言 Java数据类型分为两大类 八大字节类型(重点) Java数据类型拓展 整数拓展:进制 浮点数拓展 字符类型 布尔值拓展 数据类型 强类型语言 要求变量的使用要 ...
- SElinux管理
SElinux: 是Linux的一个强制访问控制的安全模块 SElinux的相关概念: 对象:文件.目录.进程.端口等 主体:进程称为主体 SElinux将所有的文件都赋予一个type类型的标签,所有 ...
- CVI中调用数据库的几点..
1.各类开发工具开发的程序调用数据库,有两种方式:ADO和ODBC. 2.以ODBC方式访问SQL数据库,必须在电脑管理工具----ODBC管理器 中配置TCP/IP项(IP1.IP2.IP3.IPA ...