在 Windows 零碎上是不是看惯了千篇一律的矩形窗口?想做一些不一样的特效却只能在本人的窗口范畴内玩?而本文将带你做一个真切的阳光特效,能够真正地照亮你桌面上的其余窗口和图片,为你的利用带来不一样的特效体验!全程应用 GPU 减速,具备超高性能,而且代码超级简略。
成果预览
先放上两张动图看看成果,GIF 比拟大,如果看不到能够返回上面备注的链接查看。
阳光扫过云层:
阳光扫过 Visual Studio:
能够看到,阳光通过云层时,强烈的光辉与云层的光光局部叠加起来了,让人感觉云层的照亮局部非常扎眼。阳光通过 Visual Studio 的界面时,纯色局部能够看出阳光的形状,高饱和度局部在阳光的照耀下显得分外亮眼。
阳光扫过云层:
https://blog.walterlv.com/sta…
阳光扫过 Visual Studio:
https://blog.walterlv.com/sta…
代码实现
实现本文成果的代码其实很少,只有以下几步:
- 制作一个全透明窗口
- 编写一个像素着色器
- 画一个简略的阳光形态
不过在开始之前,咱们先创立一个空白的 WPF 我的项目吧:
第一步:制作一个全透明窗口
网上广为流传的 AllowsTransparency="True"
的形式就能够,不过我集体不喜爱,因为性能不好。我更举荐大家应用我另一篇博客里举荐的高性能通明窗口的实现计划:WPF 制作高性能的通明背景异形窗口
如果当初不想看的,我能够间接把 MainWindow.xaml.cs 的代码贴出来(释怀,其余中央不须要写代码):
<Window x:Class="Walterlv.DesktopSunshine.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Walterlv.DesktopSunshine"
mc:Ignorable="d" Title="Walterlv.DesktopSunshine" Width="240" Height="240"
Background="Transparent" WindowStyle="None" ResizeMode="NoResize">
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="-1" ResizeBorderThickness="0" CornerRadius="0" CaptionHeight="240" />
</WindowChrome.WindowChrome>
<Grid>
</Grid>
</Window>
最重要的,是 Background="Transparent"
、WindowStyle="None"
、ResizeMode="NoResize"
和 GlassFrameThickness="-1"
这四个属性。
其余的代码,我只是在做一个一般的窗口而已。大小 240 是为了包容一个太阳的大小。
WPF 制作高性能的通明背景异形窗口:
https://blog.walterlv.com/pos…
第二步:编写一个像素着色器
想理解怎么写像素着色器的,能够浏览我的另一篇博客:WPF 像素着色器入门:应用 Shazzam Shader Editor 编写 HLSL 像素着色器代码。
须要在像素着色器里编写此代码。
sampler2D inputSampler : register(S0);
float Threshold : register(C0);
float4 main(float2 uv : TEXCOORD) : COLOR
{float4 color = tex2D(inputSampler, uv);
float a = color.a;
if(a < Threshold)
{color.a = 0;}
else
{color.a = 1;}
return color;
}
将你本人编译进去的文件放到解决方案中的任意地位(本示例中放到了 Assets 文件夹中):
重要:接着,将 .ps 文件退出到编译。请双击我的项目(Walterlv.DesktopSunshine)以编辑其我的项目文件(.csproj)。须要减少的行我曾经在上面高亮进去了。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
++ <ItemGroup>
++ <Resource Include="Assets\**\*.ps" />
++ </ItemGroup>
</Project>
而后,编写一个应用此 .ps 文件的 C# 类型。我取名为 BinaryAlphaEffect.cs。
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
namespace Walterlv.DesktopSunshine
{
public class BinaryAlphaEffect : ShaderEffect
{
public static readonly DependencyProperty InputProperty = RegisterPixelShaderSamplerProperty("Input", typeof(BinaryAlphaEffect), 0);
public static readonly DependencyProperty ThresholdProperty = DependencyProperty.Register("Threshold", typeof(double), typeof(BinaryAlphaEffect),
new UIPropertyMetadata(1.0d, PixelShaderConstantCallback(0)));
public BinaryAlphaEffect()
{
PixelShader = new PixelShader
{UriSource = new Uri("/Assets/BinaryAlphaEffect.ps", UriKind.Relative),
};
UpdateShaderValue(InputProperty);
UpdateShaderValue(ThresholdProperty);
}
public Brush Input
{get => (Brush)GetValue(InputProperty);
set => SetValue(InputProperty, value);
}
public double Threshold
{get => (double)GetValue(ThresholdProperty);
set => SetValue(ThresholdProperty, value);
}
}
}
这个 Threshold
是个二值化的阈值,可用来调阳光成果。我把默认值设为了 1,这样阳光成果最强烈。(实际上其余值的成果惨不忍睹。因为这段代码我原本编写的目标不是在做阳光,只是两头不小心做出了阳光成果,觉得很有意思就教大家一下。)
应用 Shazzam Shader Editor 编写 HLSL 像素着色器代码:
https://blog.walterlv.com/pos…
第三步:画一个简略的太阳形态
我只画一个圆来示意阳光的形态(想用其余形态的,本人施展创意)。于是在 MainWindow.xaml 里增加一点点代码:
</WindowChrome.WindowChrome>
++ <Border>
++ <Ellipse Fill="White" Width="160" Height="160">
++ <UIElement.Effect>
++ <BlurEffect Radius="40" />
++ </UIElement.Effect>
++ </Ellipse>
++ </Border>
</Window>
这里,给圆加了一些含糊成果,这是必要的。
而后,把咱们在第二步里写的像素着色器用上:
<Border>
++ <UIElement.Effect>
++ <local:BinaryAlphaEffect />
++ </UIElement.Effect>
<Ellipse Fill="White" Width="160" Height="160">
<UIElement.Effect>
<BlurEffect Radius="40" />
</UIElement.Effect>
</Ellipse>
</Border>
那么至此,所有代码曾经实现。
总结一下,咱们写了这些代码:
- 一个新创建的 WPF 我的项目模板(蕴含模板自带的 App.xaml App.xaml.cs MainWindow.xaml MainWindow.xaml.cs AssemblyInfo.cs)
- 下载或编译的 BinaryAlphaEffect.ps 像素着色器文件,和用来应用它的 BinaryAlphaEffect.cs 文件
- 应用 BinaryAlphaEffect 类的 MainWindow.xaml 中的几个 Border 和 Ellipse
是不是代码量非常少?接下来,就是见证奇观的时刻。
成果与性能
阳光扫过 Windows 11 自带壁纸。在太阳左近,与太阳融为一体;在森林中,阳光被树叶遮挡;在水面,阳光跟随着波光闪耀;在岩石上,阳光把岩石照得通亮。
你能够把这个阳光放到任何中央,就算是正在播放的视频后面也仍然在每帧中都有实时成果。
最重要的是——它简直不耗费性能!因为它在图形渲染管线的像素着色器局部运行,其所有代码都在 GPU 中并行执行,且每次执行仅需不到 10 条指令。你能够看到工作管理器中,它的 CPU 和 GPU 耗费都是 0。
本文会常常更新,请浏览原文:
https://blog.walterlv.com/pos…,以防止古老谬误常识的误导,同时有更好的浏览体验。
阳光扫过 Windows 11 自带壁纸:
https://blog.walterlv.com/sta…
微软最有价值专家是微软公司授予第三方技术专业人士的一个寰球奖项。27 年来,世界各地的技术社区领导者,因其在线上和线下的技术社区中分享专业知识和教训而取得此奖项。
MVP 是通过严格筛选的专家团队,他们代表着技术最精湛且最具智慧的人,是对社区投入极大的激情并乐于助人的专家。MVP 致力于通过演讲、论坛问答、创立网站、撰写博客、分享视频、开源我的项目、组织会议等形式来帮忙别人,并最大水平地帮忙微软技术社区用户应用 Microsoft 技术。
更多详情请登录官方网站:
https://mvp.microsoft.com/zh-cn