前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[WPF]使用HLSL实现百叶窗动效

[WPF]使用HLSL实现百叶窗动效

作者头像
czwy
发布2023-10-22 15:10:07
1920
发布2023-10-22 15:10:07
举报
文章被收录于专栏:czwy的博客czwy的博客

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

image
image

准备工作与实现

  • 编写和编译HLSL代码,创建ShaderEffect。由于HLSL有自己的语言语法,本文不做讨论。这里使用一个已有的的HLSL文件,也是后边将介绍的一个HLSL编辑器工具Shazzam Shader Editor中的案例。
  • 定义像素着色器,在UI元素中使用像素着色器,并通过动画设置百叶窗动画。 百叶窗效果的像素着色器代码中:
代码语言:javascript
复制
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的加载时触发动画设置百叶窗叶片打开的进度。

代码语言:javascript
复制
<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代码。

image
image
HLSL代码编辑窗口

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

预览调节窗口

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

image
image
生成的C#代码

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

image
image
生成的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文件的路径即可。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 准备工作与实现
  • Shazzam Shader Editor
    • HLSL代码编辑窗口
      • 预览调节窗口
        • 生成的C#代码
          • 生成的VB代码
            • 在WPF中使用用HLSL
            相关产品与服务
            命令行工具
            腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档