WPF Effect: Adding Parameter to Custom Effect
Pada postingan sebelumnya, kita telah mengetahui bagaimana membuat sebuah GrayscaleEffect yang “menghilangkan” warna dari elemen UI. Dalam Effect ini kita tidak menggunakan parameter apapun (hanya <fx:GrayscaleEffect /> saja). Kali ini saya akan mencoba menjelaskan sedikit, bagaimana menambahkan parameter untuk GrayscaleEffect. Kita akan menambahkan parameter GrayStrength yang mengatur seberapa banyak warna yang akan diubah menjadi grayscale. Dan dengan sedikit mengutak-atik, kita bahkan bisa membuat animasi UI yang perlahan-lahan berubah dari berwarna menjadi grayscale, sama seperti Windows XP ketika akan di-shutdown.
KODE SHADER
Dari program yang telah dibuat pada postingan sebelumnya, pertama-tama kita ubah kode Grayscale.fx menjadi seperti di bawah:
sampler2D implicitInput : register(s0);
float grayStrength : register(c0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 color = tex2D(implicitInput, uv.xy);
float4 newcolor;
newcolor = (color.r + color.g + color.b) * 0.33333333 * grayStrength;
newcolor.rgb += color.rgb * (1 - grayStrength);
newcolor.a = color.a;
return newcolor;
}
kode shader di atas:
- menambahkan parameter grayStrength pada register “c0”
- mengalikan grayStrength sebagai intensitas warna grayscale, dan
- menambahkan komponen RGB dengan intensitas (1 – grayStrength)
nilai grayStrength adalah bilangan desimal dari 0.0 sampai 1.0.
Kemudian kompilasi lagi kode .fx ini dengan DirectX (fxc.exe) menjadi file .ps dengan cara yang sama seperti pada tutorial sebelumnya.
NB: untuk lebih detail mengenai kode HLSL bisa dilihat di MSDN
PEMBUNGKUS EFFECT DALAM C#
Untuk pembungkus dalam C#, kita cukup menambahkan property GrayStrength, property GrayStrengthProperty, dan kode UpdateShaderValue untuk GrayStrengthProperty dalam konstruktor GrayscaleEffect.
- using System;
- using System.Windows;
- using System.Windows.Media;
- using System.Windows.Media.Effects;
-
- namespace GrayscaleEffect
- {
- public class GrayscaleEffect : ShaderEffect
- {
- public GrayscaleEffect()
- {
- PixelShader =
- new PixelShader()
- {
- UriSource = new Uri("pack://application:,,,/GrayscaleEffect;component/Grayscale.ps")
- };
- UpdateShaderValue(InputProperty);
- UpdateShaderValue(GrayStrengthProperty);
- }
-
- public Brush Input
- {
- get { return (Brush)GetValue(InputProperty); }
- set { SetValue(InputProperty, value); }
- }
-
- public double GrayStrength
- {
- get { return (double)GetValue(GrayStrengthProperty); }
- set { SetValue(GrayStrengthProperty, value); }
- }
-
- public static DependencyProperty InputProperty =
- ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(GrayscaleEffect), 0);
-
- public static DependencyProperty GrayStrengthProperty =
- DependencyProperty.Register("GrayStrength", typeof(double), typeof(GrayscaleEffect),
- new UIPropertyMetadata(new double(), PixelShaderConstantCallback(0)));
- }
- }
-
Pada kode di atas, assignment untuk GrayStrengthProperty cukup panjang. Dan terdapat kode seperti
- new UIPropertyMetadata(new double(), PixelShaderConstantCallback(0))
Ini digunakan untuk menyinkronkan penambahan parameter grayStrength pada kode shader Grayscale.fx yang ditempatkan pada (register “c0” == PixelShaderConstantCallback(0) ). Apabila terdapat lebih dari 1 parameter yang ditambahkan, maka bisa digunakan register c1, c2, dst…. Tentu saja dengan penambahan juga pada pembungkus C#.
Setelah selesai menambahkan kode di atas, rebuild project Class Library GrayscaleEffect.
KODE WPF APPLICATION
Sekarang, apabila kita meng-apply GrayscaleEffect pada sebuah image dengan sintaks sebagai berikut:
- <Image Margin="12,12,66,100" Name="image1" Stretch="Fill" Source="nature.jpg">
- <Image.Effect>
- <fx:GrayscaleEffect />
- </Image.Effect>
- </Image>
maka image akan terlihat berwarna, bukan grayscale. Hal ini terjadi karena kita belum mengeset parameter GrayStrength pada kode XAML. Apabila ditambahkan parameter GrayStrength pada XAML seperti di bawah,
- <fx:GrayscaleEffect GrayStrength="0.8" />
maka akan terlihat image berubah menjadi sedikit grayscale, namun masih sedikit berwarna.
ANIMASI EFFECT
Sekarang, bagian serunya. Kita akan membuat animasi image yang perlahan-lahan menjadi grayscale.
Pertama-tama, ubah Effect pada kode XAML
- <fx:GrayscaleEffect x:Name="gsfx" />
Lalu, tambahkan kode event handler untuk komponen Window pada UI untuk Event Window_Loaded seperti di bawah.
- private void Window_Loaded(object sender, RoutedEventArgs e)
- {
- gsfx.BeginAnimation(GrayscaleEffect.GrayscaleEffect.GrayStrengthProperty,
- new DoubleAnimation(0.0, 1.0, new Duration(new TimeSpan(0, 0, 3))));
- }
-
Jalankan program dengan menekan F5, dan lihat image yang perlahan-lahan berubah menjadi grayscale dalam 3 detik ( TimeSpan(0,0,3) ). :D