WPFでは標準のエフェクトとして、BlurEffect, DropShadowEffectクラスが用意されています。WPFではブラーやドロップシャドウ以外の効果を与えたい場合には独自のエフェクトを作成できます。
ここでは、独自の効果を作成し、UIElement.Effectに適用する手順を紹介します。
まず、どのような効果を画面に対して適用するかを決定する必要があります。効果はピクセルシェーダーとして実装します。ピクセルシェーダーの記述にはHLSLと呼ばれる言語を用いて記述します。今回は、シンプルな例として画像に波紋の効果を与えるシェーダーを記述します。WateryEffect.fxという名前でテキストファイルを作成し、以下のコードを記述します。
sampler2D input : register(S0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
uv.y = uv.y + (sin(uv.y*100)*0.03);
return tex2D( input , uv.xy);
}
※WateryEffects.fxの文字コードはSHIFT-JISで記述します。
記述したWateryEffect.fxをコンパイルします。コンパイルの詳細はこちらで紹介しています。
を実行します。
でもよいです。(ピクセルシェーダーのバージョンが変わります。)
とメッセージが表示され、コンパイルが成功したことを確認します。
WateryEffect.fxを配置したディレクトリにWateryEffect.psファイルがあることを確認します。
WPFアプリケーションを作成します。
新規プロジェクト作成で[WPFアプリケーション]を選択しWPFアプリケーションを作成します。ソリューションエクスプローラのポップアップメニューの[追加]メニューの[既存の項目]メニューから、先ほどコンパイルしたHLSLファイルとコンパイル結果のファイル(WateryEffect.fxとWateryEffect.ps)をプロジェクトに追加します。
次に、カスタムエフェクトクラスを作成します。ソリューションエクスプローラの[追加]メニューの[新しい項目]メニューを選択し[クラス]を追加します。クラス名(ファイル名)は"WateryEffect"とします。
WateryEffect.csを実装します。以下のコードを記述します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
namespace WpfEffects
{
class WateryEffect : ShaderEffect
{
public WateryEffect()
{
PixelShader ps = new PixelShader();
string path = System.IO.Path.GetFullPath(@"WateryEffect.ps");
ps.UriSource = new Uri(path);
this.PixelShader = ps;
UpdateShaderValue(InputProperty);
}
public Brush Input
{
get { return (Brush)GetValue(InputProperty); }
set { SetValue(InputProperty, value); }
}
public static readonly DependencyProperty InputProperty
= ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(WateryEffect), 0);
}
}
続いてフォームを設計します。
下図のフォームを用意しました。
アプリケーションを実装します。以下のコードを記述します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Effects;
namespace WpfEffects
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
}
private void button3_Click(object sender, RoutedEventArgs e)
{
WateryEffect we = new WateryEffect();
button1.Effect = we;
image1.Effect = we;
}
}
}
プログラムを実行します。
button3をクリックすると以下の結果が得られます。