WPF使用HLSL實(shí)現(xiàn)百葉窗動畫效果
百葉窗動畫是制作PPT時(shí)常用的動畫之一,本文將通過實(shí)現(xiàn)百葉窗動畫效果的例子介紹在WPF中如何使用ShaderEffect。ShaderEffect是使用高級著色器語言(High Level Shading Language,HLSL)事先制作好并且已經(jīng)編譯過的效果。先看下百葉窗動畫實(shí)現(xiàn)效果:

準(zhǔn)備工作與實(shí)現(xiàn)
- 編寫和編譯HLSL代碼,創(chuàng)建ShaderEffect。由于HLSL有自己的語言語法,本文不做討論。這里使用一個(gè)已有的的HLSL文件,也是后邊將介紹的一個(gè)HLSL編輯器工具Shazzam Shader Editor中的案例。
- 定義像素著色器,在UI元素中使用像素著色器,并通過動畫設(shè)置百葉窗動畫。
百葉窗效果的像素著色器代碼中:
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表示百葉窗葉片打開的進(jìn)度,NumberOfBlinds是百葉窗葉片的數(shù)量,Texture2是百葉窗葉片的紋理(通常使用一個(gè)純色的圖片)。
使用百葉窗效果時(shí),只需在resources中添加著色器和動畫,并對目標(biāo)UI元素的Effect設(shè)置為百葉窗動畫。為了展示效果,本例用圖片111.jpg作為grid的背景,用純色圖片blinds.jpg作為葉片紋理。在grid的加載時(shí)觸發(fā)動畫設(shè)置百葉窗葉片打開的進(jìn)度。
<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是一個(gè)免費(fèi)的專門為 WPF 實(shí)現(xiàn)像素著色器而設(shè)計(jì)的一款編輯器,使用它來編寫像素著色器,可以自動生成WPF中的ShaderEffect。
Shazzam Shader Editor已經(jīng)好久沒有維護(hù)了,其官網(wǎng)似乎也沒了。原本開源在CodePlex上,而 CodePlex 已經(jīng)關(guān)閉。但JohanLarsson 將其 Fork 到了 GitHub 上,https://github.com/JohanLarsson/Shazzam。
打開Shazzam Shader Editor,左側(cè)顯示著色器示例和全局設(shè)置(默認(rèn)折疊)。選中具體的著色器后,右側(cè)區(qū)域上方顯示著色其效果,下方選項(xiàng)卡分別顯示HLSL代碼編輯窗口、預(yù)覽調(diào)節(jié)窗口、生成的C#代碼和生成的VB代碼。

HLSL代碼編輯窗口
HLSL代碼文件是以.fx作為后綴名。編譯后的文件后綴名是.ps。編輯窗口中可以編輯修改代碼,按下F5就可以編譯你的HLSL代碼,并在界面上方預(yù)覽效果。編輯器中會高亮關(guān)鍵詞和方法,雙擊不要松開鼠標(biāo)會彈出相應(yīng)的提示。如何編寫HLSL代碼可以查閱HLSL and Pixel Shaders for XAML Developers這本書,Shazzam Shader Editor中左側(cè)示例中的Tutorial也是配合該書使用的。
預(yù)覽調(diào)節(jié)窗口
在這里可以設(shè)置各種預(yù)覽參數(shù),預(yù)覽HLSL代碼的效果。

生成的C#代碼
這里是Shazzam Shader Editor自動生成的用C#編寫的ShaderEffect,本文前邊提到的百葉窗效果的像素著色器代碼也就是從這里直接拷貝過去的。這里的代碼默認(rèn)的命名空間是Shazzam.Shaders,代碼縮進(jìn)是用Tab??梢栽谥鞔绑w左側(cè)的全局設(shè)置中修改。

生成的VB代碼
這里和生成C#代碼一樣,只是提供VB語言編寫的ShaderEffect。
在WPF中使用用HLSL
Shazzam Shader Editor編譯HLSL后會生成XXX.ps、XXX.cs、XXX.vb三個(gè)文件,并保存在%LocalAppData%\Shazzam\GeneratedShaders目錄下的XXXEffect目錄中。這里的XXX就是你定義的HLSL的名稱。
在WPF中使用時(shí),需把XXX.ps文件以Resource的形式添加到工程中,然后把XXX.cs文件添加到工程,并根據(jù)項(xiàng)目結(jié)構(gòu),修改XXX.cs中引用XXX.ps文件的路徑即可。
到此這篇關(guān)于WPF使用HLSL實(shí)現(xiàn)百葉窗動畫效果的文章就介紹到這了,更多相關(guān)WPF百葉窗內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#利用反射來判斷對象是否包含某個(gè)屬性的實(shí)現(xiàn)方法
這篇文章主要介紹了C#利用反射來判斷對象是否包含某個(gè)屬性的實(shí)現(xiàn)方法,很有借鑒價(jià)值的一個(gè)技巧,需要的朋友可以參考下2014-08-08
C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的應(yīng)用(下)
本篇文章是對C#中ExpandoObject,DynamicObject,DynamicMetaOb的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C#不重復(fù)輸出一個(gè)數(shù)組中所有元素的方法
這篇文章主要介紹了C#不重復(fù)輸出一個(gè)數(shù)組中所有元素的方法,涉及C#針對數(shù)組的遍歷、校驗(yàn)及排序等操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08

