WPF使用HLSL实现百叶窗动画效果

 更新时间:2023年09月07日 08:23:39   作者:czwy  
百叶窗动画是制作PPT时常用的动画之一,本文将通过实现百叶窗动画效果的例子介绍在WPF中如何使用ShaderEffect,感兴趣的小伙伴可以了解一下

百叶窗动画是制作PPT时常用的动画之一,本文将通过实现百叶窗动画效果的例子介绍在WPF中如何使用ShaderEffect。ShaderEffect是使用高级着色器语言(High Level Shading Language,HLSL)事先制作好并且已经编译过的效果。先看下百叶窗动画实现效果:

准备工作与实现

  • 编写和编译HLSL代码,创建ShaderEffect。由于HLSL有自己的语言语法,本文不做讨论。这里使用一个已有的的HLSL文件,也是后边将介绍的一个HLSL编辑器工具Shazzam Shader Editor中的案例。
  • 定义像素着色器,在UI元素中使用像素着色器,并通过动画设置百叶窗动画。
    百叶窗效果的像素着色器代码中:
public class BlindsShader : ShaderEffect
{
    public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(BlindsShader), 0);
    public static readonly DependencyProperty ProgressProperty = DependencyProperty.Register("Progress", typeof(double), typeof(BlindsShader), new UIPropertyMetadata(((double)(30D)), PixelShaderConstantCallback(0)));
    public static readonly DependencyProperty NumberOfBlindsProperty = DependencyProperty.Register("NumberOfBlinds", typeof(double), typeof(BlindsShader), new UIPropertyMetadata(((double)(5D)), PixelShaderConstantCallback(1)));
    public static readonly DependencyProperty Texture2Property = ShaderEffect.RegisterPixelShaderSamplerProperty("Texture2", typeof(BlindsShader), 1);
    public BlindsShader()
    {
        PixelShader pixelShader = new PixelShader();
        pixelShader.UriSource = new Uri("/WPFTest;component/Shader/ShaderSource/BlindsShader.ps", UriKind.Relative);
        this.PixelShader = pixelShader;
        this.UpdateShaderValue(InputProperty);
        this.UpdateShaderValue(ProgressProperty);
        this.UpdateShaderValue(NumberOfBlindsProperty);
        this.UpdateShaderValue(Texture2Property);
    }
    public Brush Input
    {
        get
        {
            return ((Brush)(this.GetValue(InputProperty)));
        }
        set
        {
            this.SetValue(InputProperty, value);
        }
    }
    /// <summary>The amount(%) of the transition from first texture to the second texture. </summary>
    public double Progress
    {
        get
        {
            return ((double)(this.GetValue(ProgressProperty)));
        }
        set
        {
            this.SetValue(ProgressProperty, value);
        }
    }
    /// <summary>The number of Blinds strips </summary>
    public double NumberOfBlinds
    {
        get
        {
            return ((double)(this.GetValue(NumberOfBlindsProperty)));
        }
        set
        {
            this.SetValue(NumberOfBlindsProperty, value);
        }
    }
    public Brush Texture2
    {
        get
        {
            return ((Brush)(this.GetValue(Texture2Property)));
        }
        set
        {
            this.SetValue(Texture2Property, value);
        }
    }
}

BlindsShader.ps是编译好的HLSL文件,Progress表示百叶窗叶片打开的进度,NumberOfBlinds是百叶窗叶片的数量,Texture2是百叶窗叶片的纹理(通常使用一个纯色的图片)。

使用百叶窗效果时,只需在resources中添加着色器和动画,并对目标UI元素的Effect设置为百叶窗动画。为了展示效果,本例用图片111.jpg作为grid的背景,用纯色图片blinds.jpg作为叶片纹理。在grid的加载时触发动画设置百叶窗叶片打开的进度。

<Window.Resources>
    <ImageBrush x:Key="imageBrush" ImageSource="111.jpg" />
    <ImageBrush x:Key="blindsBrush" ImageSource="blinds.jpg" />
    <local:BlindsShader x:Key="BlindsShader"
                        NumberOfBlinds="4"
                        Progress="0"
                        Texture2="{StaticResource blindsBrush}" />
    <Storyboard x:Key="DefaultBlindsShaderStoryboard" FillBehavior="HoldEnd">
        <DoubleAnimation Storyboard.TargetProperty="(UIElement.Effect).(local:BlindsShader.Progress)"
                            From="0"
                            To="100"
                            Duration="00:00:1.5" />
        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Effect)">
            <DiscreteObjectKeyFrame KeyTime="00:00:1.5" Value="{x:Null}" />
        </ObjectAnimationUsingKeyFrames>
    </Storyboard>
</Window.Resources>
<Grid Background="{StaticResource imageBrush}" Effect="{StaticResource BlindsShader}">
    <Grid.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <BeginStoryboard x:Name="sbLoaded" Storyboard="{DynamicResource DefaultBlindsShaderStoryboard}" />
        </EventTrigger>
    </Grid.Triggers>
</Grid>

Shazzam Shader Editor

可以使用任何一款编辑器编写HLSL,然后使用fxc.exe命令行工具编译(visual studio 2022或者Windows SDK for Windows中含有该工具)。但是Shazzam Shader Editor是一个免费的专门为 WPF 实现像素着色器而设计的一款编辑器,使用它来编写像素着色器,可以自动生成WPF中的ShaderEffect。

Shazzam Shader Editor已经好久没有维护了,其官网似乎也没了。原本开源在CodePlex上,而 CodePlex 已经关闭。但JohanLarsson 将其 Fork 到了 GitHub 上,https://github.com/JohanLarsson/Shazzam。

打开Shazzam Shader Editor,左侧显示着色器示例和全局设置(默认折叠)。选中具体的着色器后,右侧区域上方显示着色其效果,下方选项卡分别显示HLSL代码编辑窗口、预览调节窗口、生成的C#代码和生成的VB代码。

HLSL代码编辑窗口

HLSL代码文件是以.fx作为后缀名。编译后的文件后缀名是.ps。编辑窗口中可以编辑修改代码,按下F5就可以编译你的HLSL代码,并在界面上方预览效果。编辑器中会高亮关键词和方法,双击不要松开鼠标会弹出相应的提示。如何编写HLSL代码可以查阅HLSL and Pixel Shaders for XAML Developers这本书,Shazzam Shader Editor中左侧示例中的Tutorial也是配合该书使用的。

预览调节窗口

在这里可以设置各种预览参数,预览HLSL代码的效果。

生成的C#代码

这里是Shazzam Shader Editor自动生成的用C#编写的ShaderEffect,本文前边提到的百叶窗效果的像素着色器代码也就是从这里直接拷贝过去的。这里的代码默认的命名空间是Shazzam.Shaders,代码缩进是用Tab。可以在主窗体左侧的全局设置中修改。

生成的VB代码

这里和生成C#代码一样,只是提供VB语言编写的ShaderEffect。

在WPF中使用用HLSL

Shazzam Shader Editor编译HLSL后会生成XXX.psXXX.csXXX.vb三个文件,并保存在%LocalAppData%\Shazzam\GeneratedShaders目录下的XXXEffect目录中。这里的XXX就是你定义的HLSL的名称。

在WPF中使用时,需把XXX.ps文件以Resource的形式添加到工程中,然后把XXX.cs文件添加到工程,并根据项目结构,修改XXX.cs中引用XXX.ps文件的路径即可。

到此这篇关于WPF使用HLSL实现百叶窗动画效果的文章就介绍到这了,更多相关WPF百叶窗内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#实现获取IIS站点及虚拟目录信息的方法

    C#实现获取IIS站点及虚拟目录信息的方法

    这篇文章主要介绍了C#实现获取IIS站点及虚拟目录信息的方法,可实现获取IIS站点信息及物理路径等功能,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • C# 多线程并发编程基础小结

    C# 多线程并发编程基础小结

    本文主要介绍了C# 多线程并发编程基础小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-04-04
  • C#程序提示“正由另一进程使用,因此该进程无法访问该文件”的解决办法

    C#程序提示“正由另一进程使用,因此该进程无法访问该文件”的解决办法

    这篇文章主要介绍了C#程序提示“正由另一进程使用,因此该进程无法访问该文件”的解决办法,本文通过改写程序代码实现解决这个问题,需要的朋友可以参考下
    2015-06-06
  • C#中IntPtr类型的具体使用

    C#中IntPtr类型的具体使用

    本文主要介绍了C#中IntPtr类型的具体使用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • c# 如何用lock解决缓存击穿

    c# 如何用lock解决缓存击穿

    这篇文章主要介绍了c# 如何用lock解决缓存击穿,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2021-02-02
  • 使用C#实现隐藏Excel单个和多个工作表的示例详解

    使用C#实现隐藏Excel单个和多个工作表的示例详解

    许多 Excel 文件中往往包含用于计算、中间处理或内部引用的数据工作表,这些内容并不需要对最终用户展示,下面我们就来看看如何使用C#实现隐藏Excel单个和多个工作表吧
    2025-12-12
  • C#排序算法之快速排序

    C#排序算法之快速排序

    下面给出的代码是以数组最后一个元素作为参考元素,这仅是参考元素选取的方式之一。
    2010-09-09
  • 基于C#实现的UPnP端口映射程序

    基于C#实现的UPnP端口映射程序

    本文介绍了基于C#实现的UPnP端口映射程序,该程序包含服务器端和客户端,支持TCP端口穿透和自动NAT穿透,服务器端实现UPnP端口映射和TCP服务端,客户端实现UPnP客户端类,程序支持多协议、自动重连机制和安全增强,需要的朋友可以参考下
    2026-02-02
  • C#异步编程由浅入深(二)之Async/Await的使用

    C#异步编程由浅入深(二)之Async/Await的使用

    这篇文章主要介绍了C#异步编程由浅入深(二)之Async/Await的作用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • 详解C#如何实现分割视频

    详解C#如何实现分割视频

    这篇文章主要为大家详细介绍了C#如何实现将视频文件分割成一帧帧图片的方法,文中的示例代码讲解详细,对我们学习C#有一定的帮助,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-12-12

最新评论