|開発環境|Microsoft Visual Studio Express 2013 for Windows Desktop| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|Visual C#/WPF アプリケーション| |プロジェクト名|WpfMandelbrot| #table_zebra(project, #fff, #eee) 参考 -[[Mandelbrot Set with PixelShader in WPF - CodeProject>http://www.codeproject.com/Articles/226547/Mandelbrot-Set-with-PixelShader-in-WPF]] 以下のファイルをプロジェクトに追加する。 |Mandelbrot.cs|クラス|| |Mandelbrot.fx|既存の項目|ビルド アクション:なし| |Mandelbrot.ps|既存の項目|ビルド アクション:Resource| MainWindow.xaml #highlight(xml){{ <Window x:Class="WpfMandelbrot.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfMandelbrot" Title="MainWindow" Height="500" Width="500"> <Grid Background="LightBlue"> <Grid.Effect> <local:Mandelbrot x:Name="Mandelbrot" /> </Grid.Effect> </Grid> </Window> }} MainWindow.xaml.cs #highlight(c#){{ using System; using System.Windows; using System.Windows.Input; using System.Windows.Media.Media3D; using System.Windows.Threading; namespace WpfMandelbrot { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { private DispatcherTimer intervalTimer = new DispatcherTimer(); private Point3D pos = new Point3D(0, 0, 1); public MainWindow() { InitializeComponent(); intervalTimer.Interval = TimeSpan.FromMilliseconds(30); intervalTimer.Tick += intervalTimer_Tick; intervalTimer.Start(); } private void intervalTimer_Tick(object sender, EventArgs e) { if (Keyboard.IsKeyDown(Key.Escape)) Application.Current.Shutdown(); if (Keyboard.IsKeyDown(Key.Up)) pos.Y -= pos.Z * 0.01; if (Keyboard.IsKeyDown(Key.Down)) pos.Y += pos.Z * 0.01; if (Keyboard.IsKeyDown(Key.Left)) pos.X -= pos.Z * 0.01; if (Keyboard.IsKeyDown(Key.Right)) pos.X += pos.Z * 0.01; if (Keyboard.IsKeyDown(Key.PageUp)) pos.Z *= 0.99; if (Keyboard.IsKeyDown(Key.PageDown)) pos.Z *= 1.01; Mandelbrot.Center = pos; Mandelbrot.Aspect = ActualHeight / ActualWidth; Title = string.Format("WpfMandelbrot ({0:f6},{1:f6}) {2:f6}", pos.X, pos.Y, pos.Z); } } } }} Mandelbrot.cs #highlight(c#){{ using System; using System.Reflection; using System.Windows; using System.Windows.Media.Effects; using System.Windows.Media.Media3D; namespace WpfMandelbrot { public class Mandelbrot : ShaderEffect { private static PixelShader _pixelShader = new PixelShader() { UriSource = new Uri(@"Mandelbrot.ps", UriKind.RelativeOrAbsolute) }; public Mandelbrot() { PixelShader = _pixelShader; UpdateShaderValue(CenterProperty); UpdateShaderValue(AspectProperty); } //---------------------------------------------------------------------- public Point3D Center { get { return (Point3D)GetValue(CenterProperty); } set { SetValue(CenterProperty, value); } } public static readonly DependencyProperty CenterProperty = DependencyProperty.Register("Center", typeof(Point3D), typeof(Mandelbrot), new UIPropertyMetadata(new Point3D(0, 0, 1), PixelShaderConstantCallback(0))); //---------------------------------------------------------------------- public double Aspect { get { return (double)GetValue(AspectProperty); } set { SetValue(AspectProperty, value); } } public static readonly DependencyProperty AspectProperty = DependencyProperty.Register("Aspect", typeof(double), typeof(Mandelbrot), new UIPropertyMetadata(1.0, PixelShaderConstantCallback(1))); } } }} Mandelbrot.fx #highlight(fx){{ float4 center : register(c0); float aspect : register(c1); float4 main(float2 uv : TEXCOORD) : COLOR { const int MaxIterate = 254; const float2 c = (uv - 0.5) * float2(1.0, aspect) * center.z + center.xy; float2 p = 0; int n; for (n = 0; n < MaxIterate && dot(p, p) < 4.0; n++) { p = float2(p.x * p.x - p.y * p.y, 2.0 * p.x * p.y) + c; } float4 color; if (n < MaxIterate) { float u = (float)n / (float)MaxIterate; color.rgb = float3(u, u, 1.0 - u); } else { color.rgb = 0.0; } color.a = 1.0; return color; } }} プロジェクトのプロパティ ビルド イベント/ビルド前に実行するコマンド ライン #highlight(bat){{ "C:\Program Files (x86)\Windows Kits\8.1\bin\x86\fxc.exe"^ /T ps_3_0 /Fo $(ProjectDir)Mandelbrot.ps $(ProjectDir)Mandelbrot.fx }}