Microsoft Visual Web Developer 2008 Express Edition Silverlight 3 Shazzam 1.2 |
■Silverlightでピクセルシェーダー | Prev Top Next |
今回はSilverlightでピクセルシェーダーをやります。 現在はSilverlight上で3Dを使用できないのでポストエフェクトくらいしかできませんが、それでもWeb上でピクセルシェーダーを実行できるというのは面白い試みだと思います。 とか書いてるけど既にFlashで可能だったりして(笑)。
今回のサンプルでは当サイトで紹介していないネタを実装します。 ラスタースクロールです。まあたいしたネタでないですが。
まずピクセルシェーダーの解説サイトを紹介します。
MSDN
このサイトでは、ピクセルシェーダーの実装方法を解説しています。
またHLSLを使用してピクセルシェーダーをコーディングする際に便利な開発ツールを紹介してます。
Shazzam
せっかくなのでShazzamを使用した開発スタイルを紹介します。
1.まずHLSLをコンパイルするために必要となる fxc.exe を取得する必要があります。これは DirectX SDK に添付されていますので、まずは DirectX SDK をダウンロードしてインストールしてください。
2.次にShazzamのサイトから Shazzam をインストールします。
3.Shazzamのインストールが終了したら、起動してみてください。
Shazzam
画面は大きく3分割されています。
左側は各種設定やfxファイルの変更などを行います。
右上はテスト表示で使用するサンプル画像の変更を行います。自分で用意した画像を使用することも可能です。
右下はfxファイルおよびマネージドコードのソースの内容を表示します。シェーダーのパラメータの変更を変更することも可能です。
画面構成とインターフェースは単純なので特別解説する必要もないと思うので、重要な部分だけ説明します。
かならずやらなければならないことはfxc.exeへのパスを設定することです。これをやらないとHLSLで記述されたfxファイルをコンパイルできません。
fxc.exeへのパスを設定
このように操作して設定します。なおfxc.exeがある場所は、"DirectX SDKをインストールしたルートフォルダ\Utilities\Bin\x86"です。
パスについてはSDKのバージョンによっては変更されているかもしれませんのでご注意を。
4.次にfxファイルを新規作成して、ピクセルシェーダーをコーディングします。なお、マネージドコードは修正しないで とコメントに書かれているので修正しない方がいいかと。
---RasterScroll.fx---
// 2Dテクスチャー sampler2D input : register(s0); // 周期 float Period : register(C0); // 振幅 float Amplitude : register(C1); // 波の移動 float Offset : register(C2); float4 main(float2 uv : TEXCOORD) : COLOR { float4 Color; float2 xy; xy.x = uv. x + sin( ( uv.y + Offset ) * Period ) * Amplitude; xy.y = uv.y; Color= tex2D( input , xy ); return Color; }
単純なのでソースの解説はなしで。
5.コーディングが終了したら F5 をクリックしてコンパイルします。エラーが発生した場合は右下の部分にエラーの内容と場所が表示されます。 コンパイルに成功したらpsファイルが作成されます。psファイルが出力されるフォルダは、「Tools」メニューの「Explore Compiled Shaders (*.ps)」をクリックすると表示されます。 ファイル名はfxファイル名と同じになります。このpsファイルを使用してSilverlight上でピクセルシェーダーを実行します。
6.次にSilverlight側の開発手順を説明します。まずプロジェクトを作成します。プロジェクト名はSilverlightSampleです。
ソリューションエクスプローラー
back.jpgファイルとピクセルシェーダーをコンパイルして作成されたRasterScroll.psファイルをインポートします。
7.次にRasterScroll.csファイルを作成します。このファイルにShazzamで自動生成されたマネージドコードをコピペします。 このソースコードは基本そのまま使用できますが、RasterScroll.psファイルをロードするときに使用する相対パスを次のように修正します。
//pixelShader.UriSource = new Uri("/Shazzam.Shaders;component/RasterScroll.ps", UriKind.Relative); pixelShader.UriSource = new Uri("/SilverlightSample;component/Resource/RasterScroll.ps", UriKind.Relative);
RasterScroll.csファイル内の名前空間はShazzam.Shadersとなっていてプロジェクト全体の名前空間(SilverlightSample)と異なります。 そのためパスを"/Resource/RasterScroll.ps"とするとファイルを取得できません。この場合は上記のように名前空間を指定するようにします。
8.MainPage.xamlを修正し、RasterScroll.psをロードするコントロールを指定します。
---MainPage.xaml---
<UserControl x:Class="SilverlightSample.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:shader="clr-namespace:Shazzam.Shaders" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480"> <Grid x:Name="LayoutRoot" Loaded="StartTimer"> <Image Source="Resource/back.jpg" Canvas.Left="0" Canvas.Top="0" > <Image.Effect> <shader:RasterScrollEffect Period="5.47" Amplitude="0.24" Offset="0" x:Name="Shader" /> </Image.Effect> </Image> </Grid> </UserControl>9.MainPage.csを修正します。
---MainPage.cs---
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace SilverlightSample { public partial class MainPage : UserControl { double Offset = 0.0; public MainPage() { InitializeComponent(); } // タイマーの実装 public void StartTimer(object o, RoutedEventArgs sender) { System.Windows.Threading.DispatcherTimer myDispatcherTimer = new System.Windows.Threading.DispatcherTimer(); myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000 / 60); // 1000 / 60 ミリ秒ごとにイベントを発生させるようにする myDispatcherTimer.Tick += new EventHandler(Each_Tick); // タイマーのイベントハンドラーを設定 myDispatcherTimer.Start(); // タイマー開始 } // タイマーイベント処理 public void Each_Tick(object o, EventArgs sender) { Offset += 0.01; if (Offset >= 3.14 * 2 / Shader.Amplitude) Offset -= 3.14 * 2 / Shader.Amplitude; Shader.Offset = Offset; } } }コンパイルすれば、波の形状にゆがんだ背景画像がスクロールするアニメーションが表示されると思います。
さて、今回でSilverlightネタはいったん終了します。ですが、Silverlightには他にも色々機能があります。Silverlight 4 もリリースしたしね。まあ面白い機能が見つかったら再開するかもしれませんが、ひとまずこれにて。