Makale Özeti

Bu makalede WPF 3.5 SP1 ile beraber gelen Pixel Shader kullanımına dair CodePlex üzerindeki Pixel Shader Effects Library'den faydalanalarak WPF uygulamalarında Transition (Geçiş) ve still (durağan) efektlerin kullanımına değiniyoruz.

Makale

.NET Framework 3.5 SP1 ile beraber gelen en büyük yeniliklerden biri de PixelShader kullanımının artık WPF uygulamalarında rahat bir şekilde mümkün olması. Kendi PixelShader efektlerinizi yazabileceğiniz gibi hazır kütüphanelerden de faydalanabilirsiniz. Bu yazımızda içerisinde hem normal PixelShader efektleri hem de geçiş efektleri barındıran CodePlex üzerindeki Windows Presentation Foundation Pixel Shader Effects Library kütüphanesini kullanarak efektlerin nasıl uygulandığını inceleyeceğiz.

Hazırlığımızı yapalım.

CodePlex üzerindeki Pixel Shader kütüphanesini kullanabilmemiz için öncesinde bir de Shader Effects BuildTask ve şablonlarını kurmamız gerek. Bu eklentiler doğrudan Pixel Shader efektlerinin programlanmasında kullanılıyor. Biz kendi Pixel Shader efektlerimizi programlamayacak olsak da diğer kütüphane bu eklentileri kullandığı için bilgisayarımıza kurmamız şart.

WPF Futures içerisinde bulunan Shader Effects BuildTask and Templates.zip yüklemesini aşağıdaki adresten bilgisayarınıza indirebilirsiniz.

http://www.codeplex.com/wpf/

İndirdiğiniz bu paket içerisindeki ShaderBuildTaskSetup.msi dosyasını çalıştırarak hemen kurulumu tamamlayın. Sonrasında da isterseniz Pixel Shader programlama için kullanılan şablonları da bilgisayarınıza yükleyebilirsiniz. Bunun için yükleme paketindeki Templates.zip dosyasını C:\Users\Daron\Documents\Visual Studio 2008 klasöre açmanız gerek. Bu klasör tabi ki sizin bilgisayarınızdaki kullanıcı adına göre değişecektir.

Pixel Shader Effects Library

Sıra geldi Pixel Shader Effects Library paketini CodePlex üzerinden indirmeye. Aşağıdaki adresten tüm paketi bilgisayarınıza indirip kaynak kodları ile beraber yazılmış Pixel Shader efektlerini inceleyebilir hatta paket içerisinde gelen örnek uygulamayı da kullanıp kaynak kodlarını inceleyebilirsiniz.

http://www.codeplex.com/wpffx

Yükleme paketi içerisindeki Visual Studio Solution dosyasını açarsanız karşınıza 3 ayrı proje gelecektir. "ShaderDemoApp" projesi klasik bir WPF projesi. Bu proje birazdan bahsedeceğimiz iki projeyi referans olarak alıp demo amacıyla hazırlanmış durumda. Ayrıca Solution içerisinde bir ShaderEffectLibrary bir de TransitionEffects adında projeler var. Bu projelerin her biri harici DLL kütüphaneleri halinde Compile ediliyor. ShaderEffectLibrary içerisinde standart PixelShader efektleri varken TransitionEffects içerisinde ise Pixel Shader kullanılarak hazırlanmış geçiş efektleri var.

Bu paketlerini farklı projeler içerisinde kullanmak için ister ihtiyacınız olan kütüphanenin projesini kendi solution'larınıza da ekleyin ister örnek proje üzerinden bu kütüphaneleri Compile ederek doğrudan DLL'lerini alarak farklı projelerde kullanın. Karar tamamen size kalmış.

TransitionEffects Kullanımı

Beni ilk heyecanlandıran videolar arası geçiş efektleri olduğu için hemen TransitionEffects kütüphanesinden başlayacağım. Yeni bir WPF projesi yaratarak bir önceki adımda indirdiğimiz paket içerisinde TransitionEffects projesini söz konusu WPF projesi ile aynı Solution içerisine yerleştirdim. Sonrasında WPF projesine de sağ tıklayarak "Add Reference" diyip TransitionEffects projesini WPF'e reference olarak ekledim. Böylece tüm geçiş efektlerini kullanma şansımız olacak.

Videolar arası geçiş yapacağımız için iki ayrı videoyu göstermek üzere uygulamama iki adet MediaElement ekliyorum.

<Window x:Class="Window1"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      Title="Window1"

      Height="300"

      Width="300">

  <Grid>

    <MediaElement x:Name="Birinci"

                Source="Butterfly.wmv"

                Panel.ZIndex="1" />

    <MediaElement x:Name="Ikinci"

                Source="Bear.wmv"

                Opacity="1"

                Visibility="Visible"

                Panel.ZIndex="0" />

    <Button HorizontalAlignment="Right"

          Margin="0,0,8,8"

          VerticalAlignment="Bottom"

          Width="73"

          Height="27"

          Content="Button"

          x:Name="Dugme" />

  </Grid>

</Window>

İki MediaElement ve bir de Button olan formumuza ait XAML kodunu yukarıda inceleyebilirsiniz. Bu noktada hemen dikkat etmemiz gereken şeylerden biri MediaElement'lerin ZIndex özellikleri. Hangi videonun arkada hangisinin önde olduğuna ZIndex ile karar verdim. Bunun nedeni birazdan kod ile bu sıralamayı değiştirecek olmam.

Uygulama çalıştırıldığında her iki MediaElement de farklı videolar oynatıyor olacaklar. Amacımız şu an önde olan MediaElement'ten arkadakine doğru bir geçiş efekti yaratmak.

[VB]

Me.Ikinci.SetValue(Grid.ZIndexProperty, 2)

[C#]

this.Ikinci.SetValue(Grid.ZIndexProperty, 2);

İlk olarak arkadaki MediaElement'imizi düğmeye basıldığı anda öne alıyoruz. Geçiş efektinin başlangıcında Ikinci adını verdiğimiz MediaElement otomatik olarak görünmez hale gelecek ve sonrasında da efekt ile ekranda gözükecek. Öne alma işlemini bitirdikten hemen sonra animasyonumuzu hazırlıyoruz.

[VB]

Dim Anim As New TransitionEffects.CloudRevealTransitionEffect

Dim da As New DoubleAnimation(0.0, 1.0, New Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd)

da.AccelerationRatio = 0.5

da.DecelerationRatio = 0.5

Anim.BeginAnimation(TransitionEffect.ProgressProperty, da)

[C#]

TransitionEffects.CloudRevealTransitionEffect Anim = new TransitionEffects.CloudRevealTransitionEffect();

DoubleAnimation da = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd);

da.AccelerationRatio = 0.5;

da.DecelerationRatio = 0.5;

Anim.BeginAnimation(TransitionEffect.ProgressProperty, da);

Yukarıdaki kod içerisinde de görebileceğiniz gibi Anim adını verdiğimiz animasyonumuz doğrudan TransitionEffects kütüphanesinden CloudRevealTransitionEffect adındaki efektin ta kendisi. Tabi bu efekte bir de DoubleAnimation ayarlamamız gerek, DoubleAnimation içerisinde efektin Progress (İlerleme durumu) özelliğinin 0'dan 1'e kadar geleceğini ve bu işlemin 2 saniye süreceği belirtiyoruz. Diğer ayarlar efektin hızlanma ve yavaşlama etkenleri ile ilgili.

Son olarak BeginAnimation metoduna da Dependency'miz olan ProgressProperty'yi ve DoubleAnimation nesnemizi veriyoruz. Toplamda baktığımızda DoubleAnimation üzerinden efektin sürecinin uzunluğunu belirleyerek efekti başlatmış olduk.

[VB]

Dim vb As New VisualBrush(Me.Ikinci)

vb.Viewbox = New Rect(0, 0, Me.Ikinci.ActualWidth, Me.Ikinci.ActualHeight)

vb.ViewboxUnits = BrushMappingMode.Absolute

[C#]

VisualBrush vb = new VisualBrush(this.Ikinci);

vb.Viewbox = new Rect(0, 0, this.Ikinci.ActualWidth, this.Ikinci.ActualHeight);

vb.ViewboxUnits = BrushMappingMode.Absolute;

Efekt süregelirken ekrandaki boyama işleminin yapılabilmesi için bi VisualBrush ayarlıyoruz. Bu VisualBrush doğrudan bizim Ikinci adındaki efekte uğrayacak MediaElement'e bağlanıyor. VisualBrush'ın genişlik ve yüksekliğini de ayarladıktan sonra artık kendisini Anim değişkenimize teslim edebiliriz.

[VB]

        Anim.OldImage = vb

        Me.Ikinci.Effect = Anim

[C#]

Anim.OldImage = vb;

this.Ikinci.Effect = Anim;

OldImage özelliği üzerinden VisualBrush'ı da aktardıktan sonra Ikinci adındaki MediaElement'e BitMapEffect olarak animasyonumuzu eşitliyoruz. Hepsi bu kadar :) Yapının biraz karışık olduğunu itiraf etmeliyim, Pixel Shader Effects kütüphanesinin kullanımı ÇOK kolay değil fakat yaptığı işi daha önceleri nasıl yapabileceğimiz ile karşılaştırırsak aslında gerçekten çok büyük bir yük kaldırdığını söyleyebiliriz.

Aşağıdaki kodu çalıştırdığınızda istediğiniz geçiş efekti ile gerçek zamanlı olarak iki video oynarken birbirleri arasında geçişler yapabildiğinizi göreceksiniz.

[VB]

    Private Sub Dugme_Click(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Dugme.Click

        Me.Ikinci.SetValue(Grid.ZIndexProperty, 2)

 

        Dim Anim As New TransitionEffects.CloudRevealTransitionEffect

 

        Dim da As New DoubleAnimation(0.0, 1.0, New Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd)

        da.AccelerationRatio = 0.5

        da.DecelerationRatio = 0.5

        Anim.BeginAnimation(TransitionEffect.ProgressProperty, da)

 

        Dim vb As New VisualBrush(Me.Ikinci)

        vb.Viewbox = New Rect(0, 0, Me.Ikinci.ActualWidth, Me.Ikinci.ActualHeight)

        vb.ViewboxUnits = BrushMappingMode.Absolute

 

        Anim.OldImage = vb

        Me.Ikinci.Effect = Anim

    End Sub

[C#]

        void Dugme_Click(object sender, RoutedEventArgs e)

        {

 

            this.Ikinci.SetValue(Grid.ZIndexProperty, 2);

 

            TransitionEffects.CloudRevealTransitionEffect Anim = new TransitionEffects.CloudRevealTransitionEffect();

 

            DoubleAnimation da = new DoubleAnimation(0.0, 1.0, new Duration(TimeSpan.FromSeconds(2.0)), FillBehavior.HoldEnd);

            da.AccelerationRatio = 0.5;

            da.DecelerationRatio = 0.5;

            Anim.BeginAnimation(TransitionEffect.ProgressProperty, da);

 

            VisualBrush vb = new VisualBrush(this.Ikinci);

            vb.Viewbox = new Rect(0, 0, this.Ikinci.ActualWidth, this.Ikinci.ActualHeight);

            vb.ViewboxUnits = BrushMappingMode.Absolute;

 

            Anim.OldImage = vb;

            this.Ikinci.Effect = Anim;

 

        }

ShaderEffects Library Kullanımı

Bir önceki bölümde geçiş efektlerini kullanırken indirdiğimiz paket içerisinden TransitionEffect projesini kopyalamıştık. Bu sefer de söz konusu paketten ShaderEffects projesini kopyalıyoruz ve kendi yarattığımız bir WPF projesi ile aynı Solution içerisine alıyoruz. Sonrasında WPF projesine sağ tıklayarak "Add Reference" diyip ShaderEffects projesini WPF'e reference olarak tanımlıyoruz. Böylece artık WPF projemizde ShaderEffects kütüphanesini rahatlıkla kullanabiliriz.

Örneğimizde hemen bir MediaElement yerleştirelim ve bu MediaElement içerisinde oynatılan videolara Pixel Shader efektleri uygulayalım.

<Window x:Class="Window1"

      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

      Title="Window1"

      Height="300"

      Width="300">

  <Grid>

    <MediaElement x:Name="Birinci"

                Source="Butterfly.wmv" />

  </Grid>

</Window>

Uygulamamız açıldığı gibi istediğimiz efekti MediaElement'e uygulamak için aslında tek yapmamız gereken uygun efekti ayarları ile ürettikten sonra Birinci adındaki MediaElement'in Effect özelliğine eşitleyerek BitmapEffect olarak atamak.

[VB]

Dim Emboss As New ShaderEffectLibrary.EmbossedEffect

Emboss.Amount = 20

Birinci.Effect = Emboss

[C#]

ShaderEffectLibrary.EmbossedEffect Emboss = new ShaderEffectLibrary.EmbossedEffect();

Emboss.Amount = 20;

Birinci.Effect = Emboss;

Hepsi bu kadar. Onlarca efekt arasında istediğinizi seçip her efektin kendine özel ayarlarını da yaptıktan sonra ister bu efektleri bir MediaElement'e ister Image nesnesine bağlayabilirsiniz. Hatta dağa da ileri gidip Container Element'lerine bile bu gibi efektler verebilirsiniz.

Hepinize kolay gelsin.