<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Greg Schechter's Blog</title><link>http://blogs.msdn.com/greg_schechter/default.aspx</link><description>&lt;a href="http://windowsclient.net/"&gt;Windows Presentation Foundation&lt;/a&gt; and &lt;a href="http://silverlight.net/"&gt;Silverlight&lt;/a&gt; -- Graphics, Media, Animation, Programming Model and other goodies.</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Effect Library posted</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/10/22/effect-library-posted.aspx</link><pubDate>Wed, 22 Oct 2008 23:13:50 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9011892</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/9011892.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=9011892</wfw:commentRss><description>&lt;p&gt;Troy Jefferson interned this summer with the WPF team and gathered a bunch of Effects that had been written by members of the WPF team.&amp;#160; These are now available for downloading on &lt;a href="http://www.codeplex.com/wpffx"&gt;CodePlex&lt;/a&gt;.&amp;#160; At that same site, you can also browse to a video of these effects in action.&lt;/p&gt;  &lt;p&gt;The single input effects in this library include:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;BandedSwirl&lt;/li&gt;    &lt;li&gt;Bloom&lt;/li&gt;    &lt;li&gt;BrightExtract&lt;/li&gt;    &lt;li&gt;ColorKeyAlpha&lt;/li&gt;    &lt;li&gt;ColorTone&lt;/li&gt;    &lt;li&gt;ContrastAdjust&lt;/li&gt;    &lt;li&gt;DirectionalBlur&lt;/li&gt;    &lt;li&gt;Embossed&lt;/li&gt;    &lt;li&gt;Gloom&lt;/li&gt;    &lt;li&gt;GrowablePoissonDiskEffect&lt;/li&gt;    &lt;li&gt;InvertColor&lt;/li&gt;    &lt;li&gt;LightStreak&lt;/li&gt;    &lt;li&gt;Magnify&lt;/li&gt;    &lt;li&gt;Monochrome&lt;/li&gt;    &lt;li&gt;Pinch&lt;/li&gt;    &lt;li&gt;Pixelate&lt;/li&gt;    &lt;li&gt;Ripple SharpenSmoothMagnify&lt;/li&gt;    &lt;li&gt;Swirl&lt;/li&gt;    &lt;li&gt;Tone&lt;/li&gt;    &lt;li&gt;Toon&lt;/li&gt;    &lt;li&gt;ZoomBlur&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There are also a set of two-input effects package up as &amp;quot;transitions&amp;quot; for doing interesting visual transitions between elements.&amp;#160; These include:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;BandedSwirl&lt;/li&gt;    &lt;li&gt;Blinds&lt;/li&gt;    &lt;li&gt;Blood&lt;/li&gt;    &lt;li&gt;CircleReveal&lt;/li&gt;    &lt;li&gt;CircleStretch&lt;/li&gt;    &lt;li&gt;CircularBlur&lt;/li&gt;    &lt;li&gt;CloudReveral&lt;/li&gt;    &lt;li&gt;Cloudy&lt;/li&gt;    &lt;li&gt;Crumble&lt;/li&gt;    &lt;li&gt;Dissolve&lt;/li&gt;    &lt;li&gt;DropFade&lt;/li&gt;    &lt;li&gt;Fade&lt;/li&gt;    &lt;li&gt;LeastBright&lt;/li&gt;    &lt;li&gt;LineReveal&lt;/li&gt;    &lt;li&gt;MostBright&lt;/li&gt;    &lt;li&gt;PixelateIn&lt;/li&gt;    &lt;li&gt;PixelateOut&lt;/li&gt;    &lt;li&gt;Pixelate&lt;/li&gt;    &lt;li&gt;RadialBlur&lt;/li&gt;    &lt;li&gt;RadialWiggle&lt;/li&gt;    &lt;li&gt;RandomCircleReveal&lt;/li&gt;    &lt;li&gt;Ripple&lt;/li&gt;    &lt;li&gt;Rotate&lt;/li&gt;    &lt;li&gt;Saturate&lt;/li&gt;    &lt;li&gt;Shrink&lt;/li&gt;    &lt;li&gt;SlideIn&lt;/li&gt;    &lt;li&gt;SmoothSwirl&lt;/li&gt;    &lt;li&gt;Swirl&lt;/li&gt;    &lt;li&gt;Water&lt;/li&gt;    &lt;li&gt;Wave. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Thanks, Troy!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9011892" width="1" height="1"&gt;</description></item><item><title>A More Useful Multi-Input Effect</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/09/27/a-more-useful-multi-input-effect.aspx</link><pubDate>Sun, 28 Sep 2008 02:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8967813</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8967813.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8967813</wfw:commentRss><description>&lt;P&gt;In &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/09/16/introducing-multi-input-shader-effects.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/09/16/introducing-multi-input-shader-effects.aspx"&gt;my last post&lt;/A&gt;, I introduced multi-input effects, where you can send in arbitrary WPF brushes that are interpreted as samplers in the shader.&amp;nbsp; The example I did just showed simple image combination via linear combination of pixel values -- illustrative, but not very useful.&lt;/P&gt;
&lt;P&gt;In this post, I'm going to demonstrate a more useful application of multi-input effects.&amp;nbsp; One of the things that TV networks and local stations do to identify themselves as programs are airing is display a little image that looks like a bit like a watermark in the lower portion of the screen.&amp;nbsp; This is subtle enough to not be distracting, but also clearly identifies the source.&amp;nbsp; This sort of subtle branding can be quite powerful.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Some do this watermarking just via a translucent icon (trivial to do in WPF without Effects).&amp;nbsp; Others use the icon in a more sophisticated way.&amp;nbsp; We're going to show a more sophisticated way here.&lt;/P&gt;
&lt;P&gt;Here is a screenshot of the sample app that's included in this post.&amp;nbsp; Note the rose logo in the lower right hand corner of the image.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_8.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_8.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=484 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_3.png" width=584 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_3.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;If you look closely at this close up, you may be able to see that the rose icon is really shifting the underlying pixels.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_10.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_10.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=107 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_4.png" width=107 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_4.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;This is known as "displacement mapping", and makes for a subtle yet distinctive effect as opposed to simply alpha blending the icon on top.&amp;nbsp; Note that here we use it on top of a static image.&amp;nbsp; However, this can be used on live video, on UI, atop DirectX content, etc.&lt;/P&gt;
&lt;H3&gt;Using the LogoDisplacer effect&lt;/H3&gt;
&lt;P&gt;The attached project includes a "LogoDisplacer" Effect.&amp;nbsp; The above is modeled as so in XAML:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Source&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="desert.jpg" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Stretch&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="None" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Loaded&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Image_Loaded"&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;lds&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;LogoDisplacer &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Logo&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StaticResource &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;logoImage&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}" 
               &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Displacement&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="20&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;AdditionalLogoOpacity&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0.4"&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; /&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;(For simplicitly, I've elided the databinding syntax that hooks the Displacement and AdditionalLogoOpacity properties to sliders.)&amp;nbsp; The "Logo" property itself is the secondary sampler input, and comes in as a reference to an ImageBrush resource in this case, defined as:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window.Resources&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ImageBrush &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Key&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="logoImage" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ImageSource&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="LogoImage.png" /&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window.Resources&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Here, LogoImage.png looks like this, but yours could be anything:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_16.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_16.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=101 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_7.png" width=102 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_7.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;This is a snapshot from Photoshop where the checkerboard represents fully transparent background pixels.&amp;nbsp; (I created this in Photoshop just by using a character from the Zapf Dingbats font, and then having the Layer Blending options set to Bevel &amp;amp; Emboss with Contouring.)&lt;/P&gt;
&lt;P&gt;The LogoDisplacer shader effect uses this logo image to displace the content under it.&amp;nbsp; It does so by, for each pixel, seeing how far the red channel is from 0.5, and offsetting in &lt;EM&gt;x&lt;/EM&gt; the lookup of the pixel from the input image by that fraction of the "Displacement" property (in pixels).&amp;nbsp; It will do the same with the green channel and the &lt;EM&gt;y&lt;/EM&gt; offset.&amp;nbsp; Thus if the image is grayscale (as in this example), red and green are the same, and the &lt;EM&gt;x&lt;/EM&gt; and &lt;EM&gt;y&lt;/EM&gt; displacement will be the same.&amp;nbsp; This is all modulated by the alpha channel of the logo, so where there are transparent pixels in the logo, no displacement occurs.&lt;/P&gt;
&lt;P&gt;After this potentially displaced lookup into the original image happens, the corresponding pixel from the logo image itself is blended in with "AdditionalLogoOpacity" alpha, to make the logo more apparent.&amp;nbsp; AdditionalLogoOpacity should be small enough to not overshadow the displacement, but big enough to allow the overlay to be discernible.&lt;/P&gt;
&lt;P&gt;When I apply the LogoDisplacer effect as constructed above, my result looks like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_12.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_12.png"&gt;&lt;IMG style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=484 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_5.png" width=584 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AMoreUsefulMultiInputEffect_155A/image_thumb_5.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Not quite the result we were hoping for, since we want the rose just in the lower right hand corner, and at it's original pixel size.&lt;/P&gt;
&lt;P&gt;The reason the rose takes up the whole image was discussed in the last post.&amp;nbsp; The sampler inputs are &lt;EM&gt;always&lt;/EM&gt; sized to match the render size of the UIElement that the effect is being applied to.&amp;nbsp; So even though our logo image is 100x100, it gets scaled up to the size of the desert image (1024x768), and that's why it's pixellated.&lt;/P&gt;
&lt;P&gt;We need to do something that prevents this resize/pixellation.&amp;nbsp; Since we know that whatever input we provide will be scaled to the size of the UIElement, we can't do a predetermined scaling -- that is, we can't create a 1024x768 image and just put the rose in the lower right hand corner, because if I apply to a UIElement of a different size, the scaling will be wrong again.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Using the Viewbox property&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;What we do instead is rely on the Viewbox property of ImageBrush.&amp;nbsp; By default, Viewbox is the unit-rect ([0,0,1,1]) that the image fills.&amp;nbsp; If we make the Viewbox larger, we can in effect position the unit-rectangle (and thus the logo) anywhere within that larger viewbox.&amp;nbsp; If I make the Viewbox be [0,0,2,2], then the logo will fill the upper left quadrant.&amp;nbsp; If I make it (-1,-1,2,2), then it will fill the lower right quadrant.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;A little math then lets us figure out how to size the Viewbox so that it fits in the lower right 100x100 pixels (or whatever the logo's pixel size is), based on the actual width and height of the UIElement.&amp;nbsp; The following is the event handler invoked when the desert image above completes loading:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private void &lt;/SPAN&gt;Image_Loaded(&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;sender, &lt;SPAN style="COLOR: #2b91af"&gt;RoutedEventArgs &lt;/SPAN&gt;e)
{
    &lt;SPAN style="COLOR: #2b91af"&gt;ImageBrush &lt;/SPAN&gt;logo = (&lt;SPAN style="COLOR: #2b91af"&gt;ImageBrush&lt;/SPAN&gt;)&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Resources[&lt;SPAN style="COLOR: #a31515"&gt;"logoImage"&lt;/SPAN&gt;];

    &lt;SPAN style="COLOR: green"&gt;// Create a viewbox so that the original logo image is in the &lt;BR&gt;    // lower right hand corner at its original pixel size (relative &lt;BR&gt;    // to the image element).
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Image &lt;/SPAN&gt;thisImage = (&lt;SPAN style="COLOR: #2b91af"&gt;Image&lt;/SPAN&gt;)sender;
    &lt;SPAN style="COLOR: #2b91af"&gt;BitmapSource &lt;/SPAN&gt;bms = logo.ImageSource &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;BitmapSource&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;double &lt;/SPAN&gt;scaleX = (&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;)thisImage.ActualWidth / bms.PixelWidth;
    &lt;SPAN style="COLOR: blue"&gt;double &lt;/SPAN&gt;scaleY = (&lt;SPAN style="COLOR: blue"&gt;double&lt;/SPAN&gt;)thisImage.ActualHeight / bms.PixelHeight;

    &lt;SPAN style="COLOR: green"&gt;// Choose viewbox to move it into the lower right.
    &lt;/SPAN&gt;logo.Viewbox = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Rect&lt;/SPAN&gt;(1.0 - scaleX, 1.0 - scaleY, scaleX, scaleY);
}&lt;/PRE&gt;
&lt;P&gt;Now, when we run the app, we get the first image shown in this post, with the logo at its correct pixel size in the lower right hand corner of the image.&lt;/P&gt;
&lt;P&gt;Note also that since the logo is just an ImageBrush, it can be made dynamic. The attached solution has the logo slowly rotating about its center.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;A note about performance&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The performance impact of a sample like this can be deceiving, since we're only showing the lower right hand corner of the element being affected.&amp;nbsp; However, remember that all pixels in the element are being examined..., but only those within the logo are being modified.&amp;nbsp; Thus, any modifications to the element itself will cause the entire effect to be re-run over the element.&amp;nbsp; So, while the GPU &lt;EM&gt;is&lt;/EM&gt; incredibly fast, there are still limits, and one should be aware of the implications.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Writing the LogoDisplacer effect&lt;/H3&gt;
&lt;P&gt;Let's move on to how the LogoDisplacer effect gets written.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The C# file&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The C# file, LogoDisplacer.cs, doesn't really have anything very interesting.&amp;nbsp; It just sets up the DependencyProperties that are bound to shader registers, as we've seen with other shaders.&amp;nbsp; In this case, there's Input (Sampler Register 0), Logo (Sampler Register 1), Displacement (Constant Register 0), and AdditionalLogoOpacity (Constant Register 1).&amp;nbsp; We also include this mellifluous property setting, which we discuss in the Appendix of this posting:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.DdxUvDdyUvRegisterIndex = 6;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;STRONG&gt;The FX file&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;This is where things get more interesting.&amp;nbsp; Here's the entire .fx file:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;//-----------------------------------------------------------------------------------------
// Shader constant register mappings (scalars - float, double, Point, Color, Point3D, etc.)
//-----------------------------------------------------------------------------------------

&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;float  &lt;/SPAN&gt;displacement : register(C0);
&lt;SPAN style="COLOR: blue"&gt;float  &lt;/SPAN&gt;additionalLogoOpacity : register(C1);
float4 ddxDdy : register(C6);

&lt;SPAN style="COLOR: green"&gt;//--------------------------------------------------------------------------------------
// Sampler Inputs (Brushes, including ImplicitInput)
//--------------------------------------------------------------------------------------

&lt;/SPAN&gt;sampler2D implicitInputSampler : register(S0);
sampler2D logoSampler : register(S1);


&lt;SPAN style="COLOR: green"&gt;//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------

&lt;/SPAN&gt;float4 main(float2 uv : TEXCOORD) : COLOR
{
   &lt;SPAN style="COLOR: green"&gt;// Pull the sample from the logo.
   &lt;/SPAN&gt;float4 logoSample = tex2D(logoSampler, uv);
   
   &lt;SPAN style="COLOR: green"&gt;// See how far away the the red and green channels are from "gray".  Use this
   // value to shift.
   &lt;/SPAN&gt;float2 fracShift = float2(0.5,0.5) - logoSample.rg;
   
   &lt;SPAN style="COLOR: green"&gt;// But first modulate the shift by the alpha in the logo.  Most of the logo is
   // transparent, so this will zero out fracShift anywhere other than the logo.
   &lt;/SPAN&gt;fracShift *= logoSample.a;
   
   &lt;SPAN style="COLOR: green"&gt;// Calculate coordinate to sample main image at, by displacing by the logo's
   // "distance from gray".  ddxDdy is used to ensure that "displacement" is treated
   // in pixel units (it maps from pixel units to [0,1] units).
   &lt;/SPAN&gt;float2 displacedCoord = uv + fracShift * displacement &lt;BR&gt;                              * float2(length(ddxDdy.xy), length(ddxDdy.zw));
    
   &lt;SPAN style="COLOR: green"&gt;// Now get the main image's color at that displaced coordinate.
   &lt;/SPAN&gt;float4 color = tex2D(implicitInputSampler, displacedCoord);
    
   &lt;SPAN style="COLOR: green"&gt;// And mix in that color with a portion of the logo, to make the logo more clearly
   // visible.  Modulate it with "additionalLogoOpacity".
   &lt;/SPAN&gt;float4 finalColor = color + logoSample * logoSample.a * additionalLogoOpacity;
   
   &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;finalColor;
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The first sections (up until "main") are just setting up the register associations that we showed in the C# file.&amp;nbsp; Then, the main() entry point:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Pulls out the color value from the logo and sees how far red and green are from 0.5 (modulating by the alpha value so it will be zero for transparent pixels).&lt;/LI&gt;
&lt;LI&gt;Figures out where to sample the main input image based upon the distances from 0.5, multiplied by the incoming "displacement" value that was in a DependencyProperty.&amp;nbsp; (The DdxDdy thing is mentioned here... we'll get there soon...)&lt;/LI&gt;
&lt;LI&gt;Now samples the main input sampler at this potentially displaced coordinate, arriving at a color.&lt;/LI&gt;
&lt;LI&gt;Finally adds in some portion of the logo pixel itself on the displaced color from the main input sampler, based upon the value of the AdditionalLogoOpacity DependencyProperty.&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This results in the subtle but visible displacement effect we see in the above images.&amp;nbsp; A running solution is attached to this post (note that it requires the &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/08/11/a-visualstudio-buildtask-and-project-and-item-templates-for-writing-shadereffects.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/08/11/a-visualstudio-buildtask-and-project-and-item-templates-for-writing-shadereffects.aspx"&gt;ShaderBuildTask from here&lt;/A&gt;.)&lt;/P&gt;
&lt;P&gt;That's all for now!&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Appendix: Advanced - a little about DdxUvDdyUvRegisterIndex&lt;/STRONG&gt; &lt;/P&gt;
&lt;P&gt;(Note that this is a fairly complicated topic that I'm not going to do full justice to in this post.)&lt;/P&gt;
&lt;P&gt;Recall that the PixelShader system samples textures within a unit square, [0,0,1,1].&amp;nbsp; However, our Displacement value is provided in pixels (which makes sense, since we typically want to display the logo at its original pixel size).&amp;nbsp; We need a way of converting from these pixel values into the unit square.&amp;nbsp; That's where DdxUvDdyUvRegisterIndex comes in.&amp;nbsp; You set it in the C# file to a constant register index, then in your shader, you access that register constant.&amp;nbsp; This constant is a float4, representing the increment in unit coordinates that the GPU needs to move when sampling to get to the next pixel to process.&amp;nbsp; The components are as follows:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;ddxDdy.x - the unit coord distance in x to move one horizontal pixel in the destination sampler.&lt;/LI&gt;
&lt;LI&gt;ddxDdy.y - the unit coord distance in y to move one horizontal pixel in the destination sampler.&lt;/LI&gt;
&lt;LI&gt;ddxDdy.z - the unit coord distance in x to move one vertical pixel in the destination sampler.&lt;/LI&gt;
&lt;LI&gt;ddxDdy.w - the unit coord distance in y to move one vertical pixel in the destination sampler.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Thus, in the above code, we multiply the Displacement by "float2(length(ddxDdy.xy), length(ddxDdy.zw))".&amp;nbsp; We take the length of x &amp;amp; y combined to tell us about the horizontal, the z &amp;amp; w combined to tell us about the vertical.&amp;nbsp; It's necessary to use all of these because if, for instance, I just used the primary components (x &amp;amp; w), but then rotated my source 90 degrees, these values would be 0, since horizontal movement no longer translated to x-coord movement in unit space.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8967813" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/greg_schechter/attachment/8967813.ashx" length="249656" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>Introducing Multi-Input Shader Effects</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/09/16/introducing-multi-input-shader-effects.aspx</link><pubDate>Tue, 16 Sep 2008 07:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8953578</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8953578.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8953578</wfw:commentRss><description>&lt;P&gt;Thus far in &lt;A title="this series on Effects" href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx"&gt;this series on Effects&lt;/A&gt;, we've discussed building and using Effects that have a single "texture" or "sampler" as input to them.&amp;nbsp; In the Beta of .NET 3.5 SP1, that's all that was available.&amp;nbsp; With the RTM release, we've added the ability to provide multiple samplers as input to the pixel shaders that drive Effects, thus substantially increasing the flexibility of what can be done with Effects.&lt;/P&gt;
&lt;P&gt;In this post, I'll show a very simple example of multi-input effects.&amp;nbsp; The result isn't anything particularly useful from a UI construction perspective, but it shows the general technique that can be used in more UI-relevant ways.&amp;nbsp; In fact, in the next post I do, I'll show something that's quite a bit more interesting from a UI perspective.&lt;/P&gt;
&lt;H2&gt;The result&lt;/H2&gt;
&lt;P&gt;I'll demonstrate a simple shader that just combines, via pixel addition, two images.&amp;nbsp; This lets me take these two images:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Toco%20Toucan_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Toco%20Toucan_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=244 alt="A toucan perched on a branch in Brazil." src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Toco%20Toucan_thumb.jpg" width=324 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Toco%20Toucan_thumb.jpg"&gt;&lt;/A&gt;&amp;nbsp;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Tree_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Tree_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=244 alt="Sheep under a tree near Dorset, England." src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Tree_thumb.jpg" width=324 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/Tree_thumb.jpg"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;and create a little app that can produce these sorts of combinations of the two:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_2.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=265 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_thumb.png" width=324 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_thumb.png"&gt;&lt;/A&gt; &lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_4.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=265 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_thumb_1.png" width=324 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_thumb_1.png"&gt;&lt;/A&gt; &lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_6.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_6.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=265 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_thumb_2.png" width=324 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroducingMultiInputShaderEffects_14F8C/image_thumb_2.png"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;H2&gt;The code&lt;/H2&gt;
&lt;P&gt;Let's first look at the XAML needed to build this.&amp;nbsp; This example, in fact, has no code at all... it's all XAML.&amp;nbsp; (At least the program that consumes the Effect... the Effect definition itself requires code.)&lt;/P&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window ... &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;  &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window.Resources&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
      &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ImageBrush &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;x&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Key&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="treeKey" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ImageSource&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;="tree.jpg" /&amp;gt;
  &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window.Resources&lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;FONT size=4&gt;&amp;gt;
&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;     &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Source&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="toucan.jpg" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1024" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Height&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;="768"&amp;gt;
         &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image.Effect&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
             &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;SimpleMultiInputEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Input2&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StaticResource &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;treeKey&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;}" &lt;BR&gt;                             &lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: red"&gt;MixInAmount&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ElementName&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=slider1, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;=Value}" /&amp;gt;
         &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image.Effect&lt;/SPAN&gt;&lt;/FONT&gt;&lt;FONT size=4&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
     &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image&lt;/SPAN&gt;&lt;/FONT&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;FONT size=4&gt;&amp;gt;
&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Margin&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="10" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Orientation&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Horizontal"&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Slider &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Minimum&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="-0.5" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Maximum&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;SmallChange&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;LargeChange&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Value&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0.5" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="slider1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="289" /&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Label &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;HorizontalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Left"  &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="label1" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;VerticalAlignment&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Bottom" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="120" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Content&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ElementName&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=slider1, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Value}" /&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;StackPanel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Window&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;FONT color=#000000&gt;The large text is the stuff that's more relevant here.&amp;nbsp; First note that we reference our tree.jpg image in an ImageBrush that's defined as a resource.&amp;nbsp; That's because all sampler inputs come in through WPF as Brushes.&amp;nbsp; In this case, it's an ImageBrush, but it could just as easily have been a VisualBrush, and thus anything that can be constructed in a WPF tree.&lt;/FONT&gt;&lt;/SPAN&gt; 
&lt;P&gt;Next, the &amp;lt;Image&amp;gt; displays the Toucan image, and we apply our custom "SimpleMultiInputEffect" to the &amp;lt;Image&amp;gt;.&amp;nbsp; Here, we set a property, Input2, as a reference to our ImageBrush holding the tree.&amp;nbsp; We also set a double-valued property MixInAmount, which is bound to the slider value.&amp;nbsp; The Effect itself lets MixInAmount control the amount of blending that Input2 will do against the primary input.&lt;/P&gt;
&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;
&lt;P&gt;Moving to the Effect definition itself.&amp;nbsp; In the C# for the Effect, the only thing notable is that we define another Brush-valued DependencyProperty:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Brush &lt;/SPAN&gt;Input2
{
    &lt;SPAN style="COLOR: blue"&gt;get &lt;/SPAN&gt;{ &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Brush&lt;/SPAN&gt;)GetValue(Input2Property); }
    &lt;SPAN style="COLOR: blue"&gt;set &lt;/SPAN&gt;{ SetValue(Input2Property, &lt;SPAN style="COLOR: blue"&gt;value&lt;/SPAN&gt;); }
}

&lt;SPAN style="COLOR: blue"&gt;public static readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DependencyProperty &lt;/SPAN&gt;Input2Property =
    &lt;SPAN style="COLOR: #2b91af"&gt;ShaderEffect&lt;/SPAN&gt;.RegisterPixelShaderSamplerProperty(&lt;SPAN style="COLOR: #a31515"&gt;"Input2"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;SimpleMultiInputEffect&lt;/SPAN&gt;), 1);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The "1" provided as the last argument to RegisterPixelShaderSamplerProperty() indicates that this Brush's realization will be available in sampler register "1" in the pixel shader.&lt;/P&gt;
&lt;P&gt;The HLSL gets a little more interesting:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;//-----------------------------------------------------------------------------------------
// Shader constant register mappings (scalars - float, double, Point, Color, Point3D, etc.)
//-----------------------------------------------------------------------------------------

float mixInAmount : register(C0);

//--------------------------------------------------------------------------------------
// Sampler Inputs (Brushes, including ImplicitInput)
//--------------------------------------------------------------------------------------

sampler2D input1 : register(S0);
sampler2D input2 : register(S1);


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------

float4 main(float2 uv : TEXCOORD) : COLOR
{
   float4 color1 = tex2D(input1, uv);
   float4 color2 = tex2D(input2, uv);
   return color1 + mixInAmount * color2;
}&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This is also very simple.&amp;nbsp; All that's happening here is that color1 and color2 are being sampled from the two input samplers (the Toucan and the Tree images, in our application), and combined according to the value of mixInAmount.&amp;nbsp; When that value is 0, we end up with pure Toucan .&amp;nbsp; When it's positive, we're adding Tree in.&amp;nbsp; When negative, we're subtracting Tree out.&amp;nbsp; All on a per-pixel basis.&lt;/P&gt;
&lt;H2&gt;More explanation&lt;/H2&gt;
&lt;P&gt;There are a few more details worth expanding on here:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;The secondary inputs get sized to the rendered size of the UIElement that the effect is being applied to.&amp;nbsp; Thus, when they make it into the shader, all the sampler inputs are the same pixel size.&amp;nbsp; You can use transforms on the incoming brushes, or viewport/viewbox, to manipulate different portions of the brush into place for finer control.&amp;nbsp; (In the above example, both the toucan image and the tree image are the same size, so it didn't matter here.) &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;You might be wondering how the initial sampler input gets its value, since we never assigned in Brush-valued resources through XAML or code in previous examples.&amp;nbsp; That's because the default for all samplers (registered via RegisterPixelShaderSamplerProperty) is a special Brush that you get from accessing Effect.ImplicitInput.&amp;nbsp; ImplicitInput just means "construct a brush from the image resulting from rendering the UIElement that this Effect is being applied to".&amp;nbsp; So, in the case above, this is the &amp;lt;Image&amp;gt; element that we have the Toucan in.&amp;nbsp; If we were applying the Effect to a Button, it'd be the rasterization of the Button. &lt;/LI&gt;&lt;/OL&gt;
&lt;H2&gt;That's it&lt;/H2&gt;
&lt;P&gt;That's it for now.&amp;nbsp; I've attached the solution that demonstrates this.&amp;nbsp; To build it, it requires the &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/08/11/a-visualstudio-buildtask-and-project-and-item-templates-for-writing-shadereffects.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/08/11/a-visualstudio-buildtask-and-project-and-item-templates-for-writing-shadereffects.aspx"&gt;Shader Build Task that I had previously written about&lt;/A&gt;.&amp;nbsp; Next time I'll show a use of multiple effects that has a more practical use for UIs than the simple blending demonstrated above.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8953578" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/greg_schechter/attachment/8953578.ashx" length="869827" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>A VisualStudio BuildTask and project and item templates for writing ShaderEffects</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/08/11/a-visualstudio-buildtask-and-project-and-item-templates-for-writing-shadereffects.aspx</link><pubDate>Tue, 12 Aug 2008 04:50:43 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8849921</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8849921.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8849921</wfw:commentRss><description>&lt;p&gt;In a number of places in &lt;a title="this series on Effects" href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx"&gt;this series on Effects&lt;/a&gt;, I've alluded to a VisualStudio BuildTask and project templates that ease the authoring of shader-based Effects.&amp;#160; We now have one up and available for you to download, install, and use.&amp;#160; This was written by Gerhard Schneider and me.&amp;#160; (Gerhard is the development lead who's team is responsible for implementing the new GPU-based Effects, among other things.)&amp;#160; We're distributing it as a CodePlex project under the Microsoft Public License.&amp;#160; You can find it at the &lt;a href="http://www.codeplex.com/wpf/Release/ProjectReleases.aspx?ReleaseId=14962"&gt;WPF Futures&lt;/a&gt; site, which is under the umbrella &lt;a href="http://www.codeplex.com/wpf"&gt;www.codeplex.com/wpf&lt;/a&gt;.&amp;#160; At that site, you'll find both a .zip file to install from, and the source code that you can peruse/modify yourself if you need to.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;Once you have this installed, you can edit .fx files and the the corresponding C# ShaderEffect subclasses all in VisualStudio, and just hit F5 or rebuild from VS to compile the whole project, including compiling the .fx file and inserting the bytecode as a resource into the resultant assembly.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;The build task and project templates can be found in &amp;quot;Shader Effects BuildTask and Templates.zip&amp;quot;, and in there you'll find a README that documents what you need to do to install.&lt;/p&gt;  &lt;p&gt;Basically what the installer does is add a BuildTask assembly to the GAC.&amp;#160; This BuildTask gets run for &amp;quot;Effect&amp;quot; labeled project files, and basically runs the HLSL compiler on them, turning a .fx file into a .ps file containing the shader bytecode.&amp;#160; That .ps file is then included in the assembly as a resource, which will get loaded into a PixelShader object.&lt;/p&gt;  &lt;p&gt;Note that the machine that this is installed on &lt;u&gt;does not&lt;/u&gt; need to have the DirectX SDK installed.&amp;#160; In this case, it will use a statically linked shader compiler to compile the .fx file into bytecode.&amp;#160; If there is a DirectX SDK installed on the machine, it will try to use the latest one as the compiler.&lt;/p&gt;  &lt;p&gt;The VS project template lets you create a new Effect Library, with the right build directive in it's .csproj file, and an initial Effect subclass and .fx file.&amp;#160; The VS item template lets you add in new Effect subclasses and .fx files to the Effect Library assembly you're building.&lt;/p&gt;  &lt;p&gt;One thing to keep in mind:&amp;#160; the created C# project references a build task that runs trusted code.&amp;#160; This will cause a dialog like the following to pop up when you open a project.&amp;#160; You should expect this and click Yes (unless of course you think my code is going to reformat your hard drive :-) ):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AVisualStudioBuildTaskandprojectanditemt_1331C/clip_image001_2.png"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="315" alt="clip_image001" src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AVisualStudioBuildTaskandprojectanditemt_1331C/clip_image001_thumb.png" width="433" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Important Note: the software referenced here is provided as-is, with no guarantees of updates/improvements/fixes/etc.&amp;#160; You're more than welcome, of course, to grab the code and modify it to suit your purposes.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8849921" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>.NET Framework 3.5SP1 and Visual Studio 2008 SP1 released!</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/08/11/net-framework-3-5sp1-and-visual-studio-2008-sp1-released.aspx</link><pubDate>Tue, 12 Aug 2008 04:28:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8849889</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8849889.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8849889</wfw:commentRss><description>&lt;p&gt;Alright!&amp;#160; .NET 3.5 SP1 and VS 2008 SP1 are &lt;a href="http://go.microsoft.com/?linkid=9330986"&gt;live and available&lt;/a&gt; on the web today.&amp;#160; There are lots of places to read about all the great stuff there, but from the perspective of this blog, the two big additions over the Beta of .NET 3.5 SP1 are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Support for multiple texture inputs to shaders used in ShaderEffects.&amp;#160; The makes ShaderEffects quite a bit more expressive and powerful.&lt;/li&gt;    &lt;li&gt;The addition of D3DImage, allowing composition-level interop between DirectX surfaces and WPF.&amp;#160; This feature opens up many, many possibilities of meaningful integration between code that already uses DirectX, or code that is more appropriately written in DirectX than in WPF.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;That's just a teaser... I'll describe these in more detail (or link to other resources that do) in upcoming posts.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8849889" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>Interested in working on the WPF team?</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/22/interested-in-working-on-the-wpf-team.aspx</link><pubDate>Thu, 22 May 2008 21:02:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8534115</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8534115.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8534115</wfw:commentRss><description>&lt;p&gt;As you can see from this and other blogs, there's lots of exciting stuff going on in WPF these days, and we're hiring!&amp;#160; Ivo Manolov, our Test Manager has &lt;a href="http://blogs.msdn.com/ivo_manolov/archive/2008/05/20/8526007.aspx"&gt;a post about job openings&lt;/a&gt; in Quality Assurance for WPF, including a posting for a Test Architect.&amp;#160; Also, &lt;a href="http://windowsclient.net/jobs/#wpf"&gt;here's a site that contains job listings&lt;/a&gt; for both Software Development positions and Quality Assurance positions.&lt;/p&gt;  &lt;p&gt;Interested?&amp;#160; Check it out!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8534115" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category></item><item><title>Writing custom Effects - adding parameters to Effects</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/15/writing-custom-effects-adding-parameters-to-effects.aspx</link><pubDate>Thu, 15 May 2008 23:15:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8509979</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8509979.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8509979</wfw:commentRss><description>&lt;p&gt;A &lt;a href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx"&gt;couple of posts ago&lt;/a&gt;, I wrote about writing custom Effects.&amp;#160; The example that I dove into was ColorComplementEffect, an Effect that has no parameters other than the incoming &amp;quot;sampler&amp;quot; that it inverts the color on.&lt;/p&gt;  &lt;p&gt;This post is going to go into what it takes to add parameters to your Effects, which allows for much, much more powerful Effects. &lt;/p&gt;  &lt;h3&gt;Shader Constants and Dependency Properties&lt;/h3&gt;  &lt;p&gt;The first thing to understand is that HLSL shaders expose &amp;quot;shader constants&amp;quot; bound to &amp;quot;shader registers&amp;quot;.&amp;#160; We saw a shader constant in the form of a &amp;quot;sampler2D&amp;quot; called &amp;quot;implicitInput&amp;quot; in the previous post on writing Effects:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;&lt;font color="#004080"&gt;sampler2D implicitInput : register(s0);&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;The parameters we discuss here will be shader constants of type float, float2, float3, or float4 in HLSL.&amp;#160; These shader constants maintain their value for an entire &amp;quot;frame&amp;quot; of the pixel shader executing across every pixel in the frame.&amp;#160; This is why they're called &amp;quot;shader constants&amp;quot;, since they're constant per-frame, though they can and often do change between frames.&lt;/p&gt;

&lt;p&gt;From an Effects point of view, they can be thought of as a property or parameter of the shader/effect.&amp;#160; And we already have a great way of dealing with properties in WPF -- we use DependencyProperties, which provides for change notification, databinding, animation, etc.&lt;/p&gt;

&lt;p&gt;So... the next step is kind of obvious...&amp;#160; we expose HLSL shader constants through custom Dependency Properties on the corresponding Effect.&lt;/p&gt;

&lt;h3&gt;An example - ThresholdEffect&lt;/h3&gt;

&lt;p&gt;Let's move to a simple example... the ThresholdEffect used &lt;a href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/using-effect-in-wpf-part-2.aspx"&gt;here&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;        &amp;lt;eff:ThresholdEffect Threshold=&amp;quot;0.25&amp;quot; BlankColor=&amp;quot;Orange&amp;quot; /&amp;gt;&lt;/pre&gt;

&lt;pre&gt;&lt;a href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_2.png"&gt;&lt;img height="273" alt="image" src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_thumb.png" width="364" border="0" /&gt;&lt;/a&gt;&lt;/pre&gt;

&lt;p&gt;This Effect just turns pixels that are below the specified Threshold intensity (0.25 in the case above) into the BlankColor (orange, in the case above).&lt;/p&gt;

&lt;p&gt;Here's the HLSL for the ThresholdEffect:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;font color="#004080"&gt;sampler2D implicitInput : register(s0);
float threshold : register(c0);
float4 blankColor : register(c1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 color = tex2D(implicitInput, uv);
    float intensity = (color.r + color.g + color.b) / 3;
    
    float4 result;
    if (intensity &amp;gt; threshold)
    {
        result = color;
    }
    else
    {
        result = blankColor;
    }
    
    return result;
}&lt;/font&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;It's a very straightforward effect.&amp;#160; It samples the texture, figures out the intensity by averaging RGB, and if above the threshold returns the sampled color, otherwise the blankColor.&lt;/p&gt;

&lt;p&gt;I'll list the entire C# for the ThresholdEffect class below, but the most important part is to understand how these properties are defined.&amp;#160; Here's one of them, Threshold:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public double &lt;/span&gt;Threshold
{
    &lt;span style="color: blue"&gt;get &lt;/span&gt;{ &lt;span style="color: blue"&gt;return &lt;/span&gt;(&lt;span style="color: blue"&gt;double&lt;/span&gt;)GetValue(ThresholdProperty); }
    &lt;span style="color: blue"&gt;set &lt;/span&gt;{ SetValue(ThresholdProperty, &lt;span style="color: blue"&gt;value&lt;/span&gt;); }
}

&lt;span style="color: blue"&gt;public static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DependencyProperty &lt;/span&gt;ThresholdProperty = 
    &lt;span style="color: #2b91af"&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style="color: #a31515"&gt;&amp;quot;Threshold&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: blue"&gt;double&lt;/span&gt;), &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;ThresholdEffect&lt;/span&gt;), 
            &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;UIPropertyMetadata&lt;/span&gt;(0.5, PixelShaderConstantCallback(0)));&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;The CLR getter/setter Threshold is identical to all CLR getter/setters for DPs... it just does a GetValue/SetValue.&amp;#160; Then the definition for ThresholdProperty is also the same as all DPs...&amp;#160; the one difference is that the PropertyChangedCallback is created via &amp;quot;PixelShaderConstantCallback(registerNumber)&amp;quot;, which generates a callback to be invoked when the property changes.&amp;#160; In this case, we pass 0 as the parameter to PixelShaderConstantCallback, since that matches the &amp;quot;threshold&amp;quot; shader constant in the HLSL that's assigned register &amp;quot;c0&amp;quot;.&lt;/p&gt;

&lt;p&gt;Once we've set this up, ThresholdProperty is just like any other DP in the system.&amp;#160; Bind to it, bind from it, animate it, etc.&lt;/p&gt;

&lt;p&gt;The only other thing we need to do is call &amp;quot;UpdateShaderValue(ThresholdProperty)&amp;quot; in the constructor of the Effect.&amp;#160; This is necessary to inform the system about this value the first time, since the PropertyChangedCallback doesn't execute when the default value is set.&amp;#160; Don't forget to call UpdateShaderValue() on each of the properties you define, including InputProperty!!&lt;/p&gt;

&lt;h3&gt;What Types are supported?&lt;/h3&gt;

&lt;p&gt;The DependencyProperties that are bound to floating point shader constant registers can be any of the following types:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Double &lt;/li&gt;

  &lt;li&gt;Single ('float' in C#) &lt;/li&gt;

  &lt;li&gt;Color &lt;/li&gt;

  &lt;li&gt;Size &lt;/li&gt;

  &lt;li&gt;Point &lt;/li&gt;

  &lt;li&gt;Vector &lt;/li&gt;

  &lt;li&gt;Point3D &lt;/li&gt;

  &lt;li&gt;Vector3D &lt;/li&gt;

  &lt;li&gt;Point4D &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They each will go into their shader register filling up whatever number of components of that register are appropriate.&amp;#160; For instance, Double and Single go into one component, Color into 4, Size, Point and Vector into 2, etc.&amp;#160; Unfilled components are set to '1'.&lt;/p&gt;

&lt;h3&gt;Some minutiae&lt;/h3&gt;

&lt;p&gt;&lt;u&gt;Register Limit&lt;/u&gt;&lt;strong&gt;:&lt;/strong&gt; There is a limit of 32 floating point registers that can be used in PS 2.0.&amp;#160; In the unlikely event that you have more values than that that you want to pack in, you might consider tricks like packing, for instance, two Points into a single Point4D, etc.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;What about int and bool registers?&lt;/u&gt;:&amp;#160; PS 2.0 doesn't deal particularly well with int and bool registers.&amp;#160; We decided to support only float registers.&amp;#160; If for some reason, you really need int or bool in your HLSL, you can cast a float register as appropriate.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;h3&gt;Complete ThresholdEffect listing&lt;/h3&gt;

&lt;p&gt;Finally, here's the entire listing for the ThresholdEffect class, which includes the Input sampler property, Threshold that we saw above, and the BlankColor property, that's managed in the exact same way that we did Threshold: &lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ThresholdEffect &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ShaderEffect
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;public &lt;/span&gt;ThresholdEffect()
    {
        PixelShader = _pixelShader;

        UpdateShaderValue(InputProperty);
        UpdateShaderValue(ThresholdProperty);
        UpdateShaderValue(BlankColorProperty);
    }

    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Brush &lt;/span&gt;Input
    {
        &lt;span style="color: blue"&gt;get &lt;/span&gt;{ &lt;span style="color: blue"&gt;return &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Brush&lt;/span&gt;)GetValue(InputProperty); }
        &lt;span style="color: blue"&gt;set &lt;/span&gt;{ SetValue(InputProperty, &lt;span style="color: blue"&gt;value&lt;/span&gt;); }
    }

    &lt;span style="color: blue"&gt;public static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DependencyProperty &lt;/span&gt;InputProperty =
        &lt;span style="color: #2b91af"&gt;ShaderEffect&lt;/span&gt;.RegisterPixelShaderSamplerProperty(&lt;span style="color: #a31515"&gt;&amp;quot;Input&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;ThresholdEffect&lt;/span&gt;), 0);


    &lt;span style="color: blue"&gt;public double &lt;/span&gt;Threshold
    {
        &lt;span style="color: blue"&gt;get &lt;/span&gt;{ &lt;span style="color: blue"&gt;return &lt;/span&gt;(&lt;span style="color: blue"&gt;double&lt;/span&gt;)GetValue(ThresholdProperty); }
        &lt;span style="color: blue"&gt;set &lt;/span&gt;{ SetValue(ThresholdProperty, &lt;span style="color: blue"&gt;value&lt;/span&gt;); }
    }

    &lt;span style="color: blue"&gt;public static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DependencyProperty &lt;/span&gt;ThresholdProperty = 
        &lt;span style="color: #2b91af"&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style="color: #a31515"&gt;&amp;quot;Threshold&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: blue"&gt;double&lt;/span&gt;), &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;ThresholdEffect&lt;/span&gt;), 
                &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;UIPropertyMetadata&lt;/span&gt;(0.5, PixelShaderConstantCallback(0)));


    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Color &lt;/span&gt;BlankColor
    {
        &lt;span style="color: blue"&gt;get &lt;/span&gt;{ &lt;span style="color: blue"&gt;return &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Color&lt;/span&gt;)GetValue(BlankColorProperty); }
        &lt;span style="color: blue"&gt;set &lt;/span&gt;{ SetValue(BlankColorProperty, &lt;span style="color: blue"&gt;value&lt;/span&gt;); }
    }

    &lt;span style="color: blue"&gt;public static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DependencyProperty &lt;/span&gt;BlankColorProperty =
        &lt;span style="color: #2b91af"&gt;DependencyProperty&lt;/span&gt;.Register(&lt;span style="color: #a31515"&gt;&amp;quot;BlankColor&amp;quot;&lt;/span&gt;, &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Color&lt;/span&gt;), &lt;span style="color: blue"&gt;typeof&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;ThresholdEffect&lt;/span&gt;), 
                &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;UIPropertyMetadata&lt;/span&gt;(&lt;span style="color: #2b91af"&gt;Colors&lt;/span&gt;.Transparent, PixelShaderConstantCallback(1)));


    &lt;span style="color: blue"&gt;private static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;PixelShader &lt;/span&gt;_pixelShader =
        &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;PixelShader&lt;/span&gt;() { UriSource = &lt;span style="color: #2b91af"&gt;Global&lt;/span&gt;.MakePackUri(&lt;span style="color: #a31515"&gt;&amp;quot;ThresholdEffect.ps&amp;quot;&lt;/span&gt;) };
}&lt;/pre&gt;&lt;/blockquote&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8509979" width="1" height="1"&gt;</description></item><item><title>A simple Effect sample project and ClickOnce application</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/13/a-simple-effect-sample-project-and-clickonce-application.aspx</link><pubDate>Wed, 14 May 2008 06:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8502830</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8502830.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8502830</wfw:commentRss><description>&lt;P&gt;The previous post in &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx"&gt;this series&lt;/A&gt; began to talk about writing custom Effects for WPF.&amp;nbsp; We looked specifically at ColorComplementEffect, an effect with no parameters.&amp;nbsp; In upcoming posts, we'll get into the details of multi-parameter effects and other specifics.&amp;nbsp; But in the meantime, I thought it would be useful to post a sample VS project and a ClickOnce application from that project for folks just itching to get going.&lt;/P&gt;
&lt;P&gt;The app looks like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AsimpleEffectsampleprojectandClickOnceap_15045/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AsimpleEffectsampleprojectandClickOnceap_15045/image_2.png"&gt;&lt;IMG style="BORDER-RIGHT: 0px; BORDER-TOP: 0px; BORDER-LEFT: 0px; BORDER-BOTTOM: 0px" height=413 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AsimpleEffectsampleprojectandClickOnceap_15045/image_thumb.png" width=404 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/AsimpleEffectsampleprojectandClickOnceap_15045/image_thumb.png"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;It's nothing fancy, mostly XAML and, in fact, the way the code and structure and UI are constructed are not conducive to hosting all effects now and forever (a more sophisticated hoster of effects would make a lot more use of metadata and reflection to allow arbitrary effects to be applied and parameters to be tweaked).&amp;nbsp; However, this definitely does the job in terms of showing how Effects are used and written.&amp;nbsp; There are two projects in the solution -- one is a MyEffects library, and the other just an EffectTest application that uses Effects from MyEffects.&lt;/P&gt;
&lt;P&gt;Note that this code and app are specific to the .NET 3.5 SP1 Beta release.&amp;nbsp; We already know of at least one breaking change in the RTM version that will require this code to be modified (just slightly).&lt;/P&gt;
&lt;P&gt;Without further ado:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://wpf.netfx3.com/direct/gregsc/SimpleEffectSample_SP1Beta/EffectTest.application" mce_href="http://wpf.netfx3.com/direct/gregsc/SimpleEffectSample_SP1Beta/EffectTest.application"&gt;Here's the ClickOnce application&lt;/A&gt; to run directly.&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/greg_schechter/attachment/8502830.ashx" mce_href="http://blogs.msdn.com/greg_schechter/attachment/8502830.ashx"&gt;Here's the .zip file of the solution&lt;/A&gt; that's attached to this post.&amp;nbsp; All but about 15K of it is taken up by the JPEG image in the background.&amp;nbsp; (The other 15K is the good stuf :-) )&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;One thing to be aware of in the solution.&amp;nbsp; The compiled pixel shaders are included as resources in the MyEffects library.&amp;nbsp; I did the fxc.exe compilation outside of the project system.&amp;nbsp; As mentioned in the last post, we have a VS BuildTask in the works that will let this be part of the project system, but until then, I included the compiled bytecode directly.&lt;/P&gt;
&lt;P&gt;Have fun!&amp;nbsp; More to come...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8502830" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/greg_schechter/attachment/8502830.ashx" length="270538" type="application/x-zip-compressed" /><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>Writing custom GPU-based Effects for WPF</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx</link><pubDate>Mon, 12 May 2008 17:08:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8491894</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>15</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8491894.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8491894</wfw:commentRss><description>&lt;P&gt;The last few posts in &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx"&gt;this series on Effects&lt;/A&gt; have focused on the perspective of those using Effects.&amp;nbsp; These Effects have to come into being somehow, and that's where we turn to now.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/gpu-accelerated-custom-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/gpu-accelerated-custom-effects-for-wpf.aspx"&gt;this post&lt;/A&gt; we showed how to apply a ColorComplementEffect to go from this to this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_2.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb.png" width=240 height=187 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_6.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_6.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_1.png" width=240 height=187 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;ColorComplementEffect, which very much looks like a photographic negative, is just about the simplest Effect one can imagine.&amp;nbsp; Conceptually, all it does is take the RGB color components and create a new color with each component subtracted from 1.0.&amp;nbsp; Let's first show what it takes to write it and add it to your app, then we'll expand and generalize from there in the next post.&lt;/P&gt;
&lt;H3&gt;Creating the HLSL for color complement&lt;/H3&gt;
&lt;P&gt;Here's some simple HLSL for doing the color complement.&amp;nbsp; Note that this series is not in the least intended to be an HLSL tutorial.&amp;nbsp; There are a bunch out on the Net, and there is also &lt;A href="http://msdn.microsoft.com/en-us/library/bb509561(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb509561(VS.85).aspx"&gt;a Programmer's Guide and Reference Guide on MSDN&lt;/A&gt; that can be a good place to start.&amp;nbsp; Also starting from existing examples (like those included here) and tweaking and experimenting is always a good approach.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;FONT color=#004080&gt;sampler2D implicitInput : register(s0);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 color = tex2D(implicitInput, uv);&lt;BR&gt;
    float4 complement;
    complement.r = color.a - color.r;
    complement.g = color.a - color.g;
    complement.b = color.a - color.b;
    complement.a = color.a;&lt;BR&gt;
    return complement;
}&lt;/FONT&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;There are a few initial things worth noting here:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;The "implicitInput" shader constant is what's in shader constant sampler register S0.&amp;nbsp; That's going to be the "original" composition of the textbox and button over the image, all converted to a "sampler".&amp;nbsp; We'll see in a bit how the association to register s0 happens. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;"main" is the entrypoint to the pixel shader.&amp;nbsp; It receives as input the texture coordinate (of type 'float2') of where we're currently outputting in the texture coordinate space of the element being applied to.&amp;nbsp; This varies from 0-1 in u and v.&amp;nbsp; Note again that while HLSL in general provides more flexibility on input types to shaders, for WPF currently, this is &lt;U&gt;always&lt;/U&gt; a float2-valued texture coordinate. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;Only a pixel shader is being provided here.&amp;nbsp; No vertex shader. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Given these, we now get to the body of the function.&amp;nbsp; The first line "tex2D" samples our input texture at the current sampling position uv, and receives a float4 (a 4-component vector with each value a float) that represents the color.&amp;nbsp; After declaring a local 'complement' float4, we proceed to assign it's R, G, and B values to&amp;nbsp;A minus the corresponding sampled value.&amp;nbsp; The A value (alpha) receives the corresponding sampled value's alpha directly.&amp;nbsp; Finally, we return that value.&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;[May 1, 2009: My esteemed colleagues Ashraf and Don pointed out that my earlier incarnation of this of (1 - component) was wrong, and it should be (A - component).&amp;nbsp; That's because color RGB has their alpha value premultiplied through already.&amp;nbsp;&amp;nbsp;(1 - component) would work for non-premultiplied.&amp;nbsp; The reason it hasn't come up when I used it was the images I supplied were all opaque (A = 1) images, and in this case (1 - component) == (A - component).]&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;When the Effect runs, this main() function is executed on &lt;EM&gt;every&lt;/EM&gt; pixel affected.&amp;nbsp; It's run very fast, and quite a bit in parallel, but it is run.&lt;/P&gt;
&lt;P&gt;The above isn't the best way to express this HLSL.&amp;nbsp; The thing is that HLSL drives a SIMD vector processor, so rather than have these three separate RGB calculations, we can use HLSL to combine them:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;FONT color=#004080&gt;float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 color = tex2D(implicitInput, uv);&lt;BR&gt;
    float4 complement;
    complement.rgb = color.a - color.rgb;
    complement.a = color.a;&lt;BR&gt;
    return complement;
}&lt;/FONT&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The syntax "complement.rgb =&amp;nbsp;color.a - color.rgb" will treat the "color.a" as replicated into each element of a 3-vector, and then do the subtraction on each element, all with a single PS 2.0 instruction.&amp;nbsp; (Actually, the HLSL compiler deduces this without me being explicit so the two above shaders generate the same number of instructions, but I never like to count on understanding exactly when compiler optimizations will or won't kick in in super performance sensitive code.)&lt;/P&gt;
&lt;H3&gt;Compiling the HLSL&lt;/H3&gt;
&lt;P&gt;WPF Effects do not take the HLSL text directly.&amp;nbsp; You need to compile it into the binary bytecode that DirectX natively accepts, which is how WPF passes it along.&amp;nbsp; To do this, you run fxc.exe on your shader file.&amp;nbsp; Fxc.exe is the shader compiler that comes with the &lt;A href="http://msdn.microsoft.com/en-us/library/aa139765.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa139765.aspx"&gt;Microsoft DirectX SDK&lt;/A&gt;.&amp;nbsp; You can find it at Utilities\Bin\x86\fxc.exe in the SDK.&lt;/P&gt;
&lt;P&gt;Say your HLSL was in 'cc.fx', the following command line would generate the compiled bytecode int 'cc.ps' in the same directory:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&amp;gt; &lt;FONT face=Consolas&gt;fxc /T ps_2_0 /E main /Focc.ps cc.fx&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This says to compile to the PS 2.0 profile, and to look for the entrypoint named "main".&lt;/P&gt;
&lt;P&gt;(We have a rough prototype that adds the fxc.exe compilation as a MSBuild build task so that it can be incorporated directly into projects without having to break out to a command line shader compiler.&amp;nbsp; When that's further along, we'll post this out there for all to use.)&lt;/P&gt;
&lt;H3&gt;Writing your managed code Effect subclass&lt;/H3&gt;
&lt;P&gt;Now it's time to write our managed code that will expose this Effect out to WPF developers.&amp;nbsp; We'll use C# here.&amp;nbsp; &lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;System;&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;System.Windows;
&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;System.Windows.Media;
&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;System.Windows.Media.Effects;

&lt;SPAN style="COLOR: blue"&gt;namespace &lt;/SPAN&gt;MyEffects
{
    &lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ColorComplementEffect &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;ShaderEffect
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;ColorComplementEffect()
        {
            PixelShader = _shader;
            UpdateShaderValue(InputProperty);
        }

        &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Brush &lt;/SPAN&gt;Input
        {
            &lt;SPAN style="COLOR: blue"&gt;get &lt;/SPAN&gt;{ &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Brush&lt;/SPAN&gt;)GetValue(InputProperty); }
            &lt;SPAN style="COLOR: blue"&gt;set &lt;/SPAN&gt;{ SetValue(InputProperty, &lt;SPAN style="COLOR: blue"&gt;value&lt;/SPAN&gt;); }
        }

        &lt;SPAN style="COLOR: blue"&gt;public static readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;DependencyProperty &lt;/SPAN&gt;InputProperty =
            &lt;SPAN style="COLOR: #2b91af"&gt;ShaderEffect&lt;/SPAN&gt;.RegisterPixelShaderSamplerProperty(
                    &lt;SPAN style="COLOR: #a31515"&gt;"Input"&lt;/SPAN&gt;, 
                    &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;ColorComplementEffect&lt;/SPAN&gt;), 
                    0);&lt;/PRE&gt;&lt;PRE class=code&gt;        &lt;SPAN style="COLOR: blue"&gt;private static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PixelShader &lt;/SPAN&gt;_shader =
            &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PixelShader&lt;/SPAN&gt;() { UriSource = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;@"pack://application:,,,/MyEffects;component/ColorComplementEffect.ps")&lt;/SPAN&gt; };

    }
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Here's basically how this works:&amp;nbsp; &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;We derive from ShaderEffect, itself a subclass of Effect.&amp;nbsp; Most importantly, ShaderEffect exposes a PixelShader property of type PixelShader. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;We define a static PixelShader instance which references the compiled bytecode.&amp;nbsp; It's static because the same PixelShader object can be shared amongst all instances of the Effect. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;We define a Brush-valued DependencyProperty called InputProperty, and the corresponding Input CLR property.&amp;nbsp; This is &lt;EM&gt;almost&lt;/EM&gt; identical to how we define other DPs in WPF.&amp;nbsp; The difference is that we use a helper method called ShaderEffect.RegisterPixelShaderSamplerProperty.&amp;nbsp; As in other DP definitions, both the name and the owning type are specified.&amp;nbsp; But the third parameter here (0, in this case) represents the sampler register that the Input property will be able to be accessed from in the shader.&amp;nbsp; Note that this 0 matches the s0 in the HLSL above: 
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;FONT color=#004080&gt;sampler2D implicitInput : register(s0);&lt;/FONT&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;UL&gt;
&lt;LI&gt;The instance constructor just assigns in the static _shader to the per-instance PixelShader property, and calls UpdateShaderValue() on any DPs that are associated with shader registers.&amp;nbsp; In this case, just the InputProperty.&amp;nbsp; This latter is necessary to ensure it's set for the first time, since DPs don't call their PropertyChangedCallbacks on the setting of their default values. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The other thing worth mentioning here is the gibberish in the "pack://" URI when we reference our pixel shader bytecode file, ColorComponentEffect.ps.&amp;nbsp; Since we don't want to reference a loose file on disk, and we'd like the shader bytecode to live in whatever packaging the C# ColorComponentEffect class goes into (since they should travel together), we use the WPF &lt;A href="http://msdn.microsoft.com/en-us/library/aa970069(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa970069(VS.85).aspx"&gt;"pack://" URI syntax&lt;/A&gt;.&amp;nbsp; In this case, we're building a library called "MyEffects", which is why that appears in the pack URI.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In order for this "pack://" URI to work, the bytecode needs to make its way into the built component.&amp;nbsp; You do this by adding the shader bytecode file into your project, and ensuring that its Build Action is set to "Resource" as this snip from the Solution Explorer shows:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroductiontowritingEffects_11298/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroductiontowritingEffects_11298/image_4.png"&gt;&lt;IMG style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroductiontowritingEffects_11298/image_thumb_1.png" width=289 height=306 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/IntroductiontowritingEffects_11298/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;I have a little helper function that lets me express this URI string without hardwiring in "MyEffects", and without re-generating this same gibberish each time: &lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;PixelShader&lt;/SPAN&gt;() { UriSource = &lt;SPAN style="COLOR: #2b91af"&gt;Global&lt;/SPAN&gt;.MakePackUri(&lt;SPAN style="COLOR: #a31515"&gt;"ColorComplementEffect.ps"&lt;/SPAN&gt;) }&lt;BR&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I include the code for the Global helper class at the bottom of this post.&lt;/P&gt;
&lt;P&gt;(Note also that PixelShader objects can also be defined via a Stream, which enables, for instance, authoring tools to construct shader bytecode on the fly and pass it to WPF without ever having to persist it to the file system.)&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;&amp;lt;Geek-Out-Alert--Somewhat-Esoteric-Stuff-Here&amp;gt;&lt;/FONT&gt;&lt;/STRONG&gt; (as if this whole topic isn't geeky enough to start with)&lt;/P&gt;
&lt;P&gt;Recall that we considered ColorComplementEffect to be a zero-parameter effect.&amp;nbsp; So what's with this "Input" DP?&amp;nbsp; Note that the Effect is invoked via this XAML:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;  &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ColorComplementEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;

    &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;
  &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN-BOTTOM: 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;The "sampler" that the shader works on is the rasterization of the Grid itself into a bitmap.&amp;nbsp; You can think of the implementation as creating a VisualBrush of the Grid, then providing that Brush as the value for the Input DP.&amp;nbsp; It doesn't quite work like that, and we expose a new type of Brush called ImplicitInput to represent this usage.&amp;nbsp; ImplicitInput is the default value for DPs that defined using "RegisterPixelShaderSamplerProperty", meaning that they automatically receive the "brush" of the element that they're applied to as their shader sampler (register 0 in this case, since that's what we specified).&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN-BOTTOM: 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;We'll see in later posts why exposing these as Brushes, and having the ability to control whether ImplicitInput is used is important.&amp;nbsp; Hint: it has to do with multi-input effects.&lt;/P&gt;
&lt;P style="LINE-HEIGHT: normal; MARGIN-BOTTOM: 0pt; mso-layout-grid-align: none" class=MsoNormal&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;&amp;lt;/Geek-Out-Alert--Somewhat-Esoteric-Stuff-Here&amp;gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;OK, that's it for this post...&amp;nbsp; in the next one we'll get into somewhat more complicated Effect definition.&amp;nbsp; In particular, parameterized effects.&lt;/P&gt;
&lt;H3&gt;Appendix: Global.MakePackUri&lt;/H3&gt;
&lt;P&gt;This is the MakePackUri helper I referenced above.&amp;nbsp; It's nice in that it's not verbose (like the pack:// URI itself), and, more importantly, it doesn't hardwire in a module name.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;internal static class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Global
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;summary&amp;gt;
    /// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;Helper method for generating a "pack://" URI for a given relative file based on the
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &lt;/SPAN&gt;&lt;SPAN style="COLOR: green"&gt;assembly that this class is in.
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: gray"&gt;/// &amp;lt;/summary&amp;gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;public static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri &lt;/SPAN&gt;MakePackUri(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;relativeFile)
    {
        &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;uriString = &lt;SPAN style="COLOR: #a31515"&gt;"pack://application:,,,/" &lt;/SPAN&gt;+ AssemblyShortName + &lt;SPAN style="COLOR: #a31515"&gt;";component/" &lt;/SPAN&gt;+ relativeFile;
        &lt;SPAN style="COLOR: blue"&gt;return new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Uri&lt;/SPAN&gt;(uriString);
    }

    &lt;SPAN style="COLOR: blue"&gt;private static string &lt;/SPAN&gt;AssemblyShortName
    {
        &lt;SPAN style="COLOR: blue"&gt;get
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(_assemblyShortName == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
            {
                &lt;SPAN style="COLOR: #2b91af"&gt;Assembly &lt;/SPAN&gt;a = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;Global&lt;/SPAN&gt;).Assembly;

                &lt;SPAN style="COLOR: green"&gt;// Pull out the short name.
                &lt;/SPAN&gt;_assemblyShortName = a.ToString().Split(&lt;SPAN style="COLOR: #a31515"&gt;','&lt;/SPAN&gt;)[0];
            }

            &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;_assemblyShortName;
        }
    }

    &lt;SPAN style="COLOR: blue"&gt;private static string &lt;/SPAN&gt;_assemblyShortName;
}&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8491894" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>More details on how Effects work</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/12/more-details-on-how-effects-work.aspx</link><pubDate>Mon, 12 May 2008 17:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8482776</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8482776.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8482776</wfw:commentRss><description>&lt;P&gt;The last couple posts in &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx"&gt;this series&lt;/A&gt;&lt;B&gt; &lt;/B&gt;have dug into features and example usage of Effects in WPF. Let’s go into some other aspects of the feature that are important to understand.&lt;/P&gt;
&lt;H3&gt;Software Rendering&lt;/H3&gt;
&lt;P&gt;When we discuss Effects, we typically talk about them being GPU-accelerated. This is typically the case. However, there are three important situations where the Effects cannot be GPU-accelerated:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;When the graphics card being run on does not support PixelShader 2.0 or above. This is becoming more and more rare, but is definitely still out there. &lt;/LI&gt;
&lt;LI&gt;When the WPF application is being remoted over Remote Desktop or Terminal Server or some other kind of mirror driver. &lt;/LI&gt;
&lt;LI&gt;When the WPF application is in a mode where software rendering is required – such as rendering to a RenderTargetBitmap, or printing. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;In all of these cases, WPF will render Effects via software. What does that mean? As mentioned in an earlier post, Effects are written using HLSL for programming the GPU. WPF incorporates a “&lt;A href="http://en.wikipedia.org/wiki/Just-in-time_compilation" mce_href="http://en.wikipedia.org/wiki/Just-in-time_compilation"&gt;JIT&lt;/A&gt;ter” (Just-in-Time compiler) that takes the compiled HLSL bytecode, validates it, and dynamically generates &lt;A href="http://en.wikipedia.org/wiki/Streaming_SIMD_Extensions" mce_href="http://en.wikipedia.org/wiki/Streaming_SIMD_Extensions"&gt;x86 SSE&lt;/A&gt; instructions that can execute the HLSL in software the same way it would be executed in the GPU. SSE stands for “Streaming SIMD instructions”, which is an indicator that it’s a decent alternative when there isn’t a GPU available. It’s certainly considerably slower than the GPU (and considerably less parallel), and obviously taxes the CPU more, but given that it’s fundamentally a SIMD processor as well, it’s quite well suited to executing HLSL. All told, we’ve been very pleased, and very pleasantly surprised with how well the CPU &lt;I&gt;does&lt;/I&gt; execute shaders in the absence of a GPU.&lt;/P&gt;
&lt;H3&gt;Interactivity&lt;/H3&gt;
&lt;P&gt;The Effects shown thus far in this series are all “in-place” effects, in the sense that they output some modification of the pixel that’s at the same location in the input texture as its destination in the output texture. That is, they just manipulate color, and not position. However, distortion types of effects, like swirls, bulges, pinches, etc., are all very powerful, important and achievable Effects. In those cases, you may get a result like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/MoredetailsonhowEffectswork_E97E/clip_image002_2.jpg" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/MoredetailsonhowEffectswork_E97E/clip_image002_2.jpg"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=274 alt=clip_image002 src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/MoredetailsonhowEffectswork_E97E/clip_image002_thumb.jpg" width=364 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/MoredetailsonhowEffectswork_E97E/clip_image002_thumb.jpg"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;It so happens that the button and the textbox in the above image remain fully interactive and operable, and you can click on their onscreen position to give them focus. How does this work? The HLSL shaders know nothing about input? The way this works is that the Effect author has an opportunity to define the “EffectMapping” that the Effect subjects its points to. The author of the Effect is responsible for returning a GeneralTransform that takes a position and returns the post-Effect corresponding position. The author also needs to provide the inverse mapping. This is then used for input testing as well as for functionality like TransformTo{Ancestor,Descendant,Visual}.&lt;/P&gt;
&lt;P&gt;(Note that GeneralTransform is a generalization of the Transform class that, while not heavily used, has existed since the first version of WPF, and represents transforms that cannot be expressed via an affine 3x2 matrix, and is thus necessary for representing the flexibility that Effects possess. They were introduced for exactly this sort of purpose.)&lt;/P&gt;
&lt;H3&gt;Full Trust Requirement&lt;/H3&gt;
&lt;P&gt;WPF will &lt;U&gt;only&lt;/U&gt; run Effects within fully-trusted applications.&amp;nbsp; There is no support currently for running Effects in partially-trusted or untrusted apps.&amp;nbsp; This is something we want to move towards in a subsequent release (particurly for the software rendering implementation).&lt;/P&gt;
&lt;H3&gt;What sort of shaders?&lt;/H3&gt;
&lt;P&gt;GPUs expose multiple types of shaders. In shader model 3.0 and prior, there are both Vertex Shaders and Pixel Shaders. PS 4.0 adds Geometry Shaders. For the WPF Effects feature, we only support the use of Pixel Shaders. Furthermore, the only value that varies on per-pixel invocation of the shader is the incoming texture coordinate (uv), representing where on the output surface the shader is running. There are a number of powerful techniques that one can potentially achieve by introducing Vertex Shaders and more flexible input data for the Pixel Shader. However, for our first time getting into the GPU programming arena, WPF is only exposing the feature via Pixel Shaders as described here.&lt;/P&gt;
&lt;H3&gt;What about BitmapEffects?&lt;/H3&gt;
&lt;P&gt;The initial release of WPF introduced a class called BitmapEffect, and a property on UIElement also called BitmapEffect. These played much the same role, conceptually, as Effects do. However, they were riddled with performance problems. The main problems with them was that a) they executed in software, and b) they executed on the UI thread. The first issue means they didn’t take advantage of the GPU. The second issue is worse, and means that the entire rendering of everything in the tree leading up to the BitmapEffect needed to be rendered in software as well. Thus, the performance impact on an application was quite considerable. For certain cases (BitmapEffects on small pixel areas that aren’t updating often) things were OK. However, one quickly fell of the performance cliff into the problems I describe above.&lt;/P&gt;
&lt;P&gt;In WPF 3.5 SP1, we still have BitmapEffects, though their use is discouraged and, in fact, they are marked [Obsolete] in the WPF assemblies, meaning that their use will generate compiler warnings. This is done so that they can be removed from the system in a future version (not sure just when that would happen), but not have existing apps that depend upon them break.&lt;/P&gt;
&lt;P&gt;Of the built-in BitmapEffects, there are two that are far and away the most commonly used: BlurBitmapEffect and DropShadowBitmapEffect. For these, we’ve built equivalent (but hardware accelerated) Effect-based versions that you can attach to UIElement.Effect now. Also, we have an “emulation” layer so that apps that are already out there that hook up UIElement.BitmapEffect to the BlurBitmapEffect or DropShadowBitmapEffect will now result in use of the Effect-based ones. (Note that this won’t work in all cases – for instance, if you use a BitmapEffectGroup, this won’t get emulated.)&lt;/P&gt;
&lt;H3&gt;Additional RenderCapability APIs&lt;/H3&gt;
&lt;P&gt;With the addition of Effects, the System.Windows.Media.RenderCapability class gets two new members to allow applications to fine-tune their use of shader-based Effects:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;IsPixelShaderVersionSupported(major, minor) will tell you whether the system being run on supports the specified Pixel Shader version on the GPU.&amp;nbsp; This is useful for understanding whether effects that you want to run will run in hardware, as you may potentially want to exclude them if they don't run in hardware. &lt;BR&gt;&lt;/LI&gt;
&lt;LI&gt;IsShaderEffectSoftwareRenderingSupported is a Boolean property that says whether the system being run on supports SSE2, which is the determinant for whether the software JITter described above will work. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;That’s it for this post, and that pretty much wraps up the general information on using Effects and some of the information surrounding their use. If you’re interested in authoring Effects, you may well be clamoring for more details there. That will be the topic of the next set of posts in this series.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8482776" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>Using Effects in WPF (Part 2)</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/12/using-effect-in-wpf-part-2.aspx</link><pubDate>Mon, 12 May 2008 17:04:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8482356</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8482356.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8482356</wfw:commentRss><description>&lt;P&gt;My &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/gpu-accelerated-custom-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/gpu-accelerated-custom-effects-for-wpf.aspx"&gt;previous post&lt;/A&gt; on Effects (part of &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx"&gt;this series&lt;/A&gt;) gives a simple example of instantiating an parameterless Effect (it just takes the complement of a color) through XAML. Here we discuss more about the use of Effects. &lt;/P&gt;
&lt;P&gt;First, lest you think that Effects are somehow a XAML-only feature, let’s write some code to use Effects. Recall that the invocation of the Effect through XAML looked like this:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;  &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ColorComplementEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;

    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;  /&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
  &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;In code, presuming I already have the Grid and it’s called “myGrid”, we’d just do the following: &lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;myGrid.Effect = &lt;SPAN style="COLOR: blue"&gt;new MyEffects.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ColorComplementEffect();
&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Like everything else in WPF, Effects are readily creatable and manipulable through code. Given that, most of the below will focus on usage through XAML just because it’s the most succinct way of expressing the usage. &lt;/P&gt;
&lt;P&gt;The ColorComplementEffect is very limited in what it can do, as it takes no parameters. Let’s look at using an Effect that does take parameters. This is an intensity-thresholding effect – for each pixel, it determines if the pixel is above a certain intensity and, if it is, outputs that pixel. Otherwise it outputs a constant color (transparent by default). The XAML below applies the ThresholdEffect with a threshold value of 0.2, and yellow as the color to fill in those pixels that are below an average 0.2 intensity. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;  &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ThresholdEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Threshold&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0.25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;BlankColor&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Orange" /&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;  /&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
  &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;The result looks like this: &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_2.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=273 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_thumb.png" width=364 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Because the ThresholdEffect class exposes Threshold and BlankColor as DependencyProperties, we can use our standard WPF techniques to databind and animate these properties. For instance, the XAML below introduces a slider and wires the Threshold value of the ThresholdEffect to the value of the slider. As you move the slider, more or less of the grid content “thresholds” in and out:&lt;/P&gt;&lt;PRE class=code&gt;   &lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
           &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ThresholdEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Threshold&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="{&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Binding &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ElementName&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=thresholdSlider, &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=Value}" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;BlankColor&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Orange" /&amp;gt;
       &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;

       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; /&amp;gt;
       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;
       &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox ...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
 &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;   &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Slider &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Name&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="thresholdSlider"&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Minimum&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Maximum&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1" ...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; /&amp;gt;
&lt;/SPAN&gt;&amp;nbsp; &lt;/PRE&gt;
&lt;H3&gt;Chaining Effects&lt;/H3&gt;
&lt;P&gt;In the world of GPU programming, there’s a concept known as “multi-pass”, where the programmer sets up multiple pixel shaders and cycles through them, with the output of one becoming the input of the next. In this release of WPF, we do not have &lt;I&gt;explicit &lt;/I&gt;support for building multi-pass effects. However, WPF provides a very natural way to express what is typically desired – namely “containment”. Say I want to apply my ThresholdEffect as above, but after that I want to apply the ColorComplementEffect.&amp;nbsp; A very simple way to do this is to take the Grid shown above, and wrap a Border around it. On this Border, add the ColorComplementEffect. Here’s the XAML: &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Border&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Border.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ColorComplementEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Border.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
            &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ThresholdEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;Threshold&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="0.25" &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;BlankColor&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Orange" /&amp;gt;
        &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;BR&gt;        &lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; /&amp;gt; &lt;BR&gt;        &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;BR&gt;        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox ...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; &lt;/SPAN&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Border&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Here’s what this looks like:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_4.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_4.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=274 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_thumb_1.png" width=364 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/UsingEffectinWPFPart2_D6D8/image_thumb_1.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;H3&gt;Multi-input Effects&lt;/H3&gt;
&lt;P&gt;The Effects described here receive a single input bitmap from the UIElement that they are attached to, and they can get an arbitrary number of “scalar” properties through DependencyProperties that the Effect author provides for his users, and that they can be chained via element containment. These “scalar” properties are things like double, Color, Point, Point3D, Vector, Vector3D, Size, etc. &lt;/P&gt;
&lt;P&gt;One thing that all the Effects thus far have in common is that they have &lt;EM&gt;exactly&lt;/EM&gt; one bitmap input... the rasterization of the UIElement that they're being applied to.&amp;nbsp; WPF also will support "multi-input" effects where multiple UIElements (or other sources of bitmap data) can be provided to and manipulated by an Effect.&amp;nbsp; (We don't consider effects like ThresholdEffect to be multi-input even though they have multiple properties/parameters...&amp;nbsp; we consider "multi-input" to mean receiving more than one bitmap input.)&lt;/P&gt;
&lt;P&gt;Multi-input effects will be part of the .NET 3.5 SP1 release, but they're not in the Beta, so we won't discuss them further here.&lt;/P&gt;
&lt;H3&gt;What have we seen?&lt;/H3&gt;
&lt;P&gt;Thus far in these posts we’ve looked at invoking GPU-accelerated Effects from your WPF applications and components. &lt;/P&gt;
&lt;P&gt;Effects actually do have more features from a “using Effects” point of view, but for now, this is a good stopping point, as what’s been described above represents the bulk of the power and flexibility of Effects. The next post, rather than giving more examples and features, will talk about some of the operational aspects that are important to know about for the stuff described above.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8482356" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>GPU-accelerated custom effects for WPF</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/12/gpu-accelerated-custom-effects-for-wpf.aspx</link><pubDate>Mon, 12 May 2008 17:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8480839</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8480839.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8480839</wfw:commentRss><description>&lt;P&gt;With WPF 3.5 SP1 on the horizon (and the &lt;A class="" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=8C36ACA4-E947-4760-9B05-93CAC04C6F87&amp;amp;displaylang=en" mce_href="http://www.microsoft.com/downloads/details.aspx?FamilyId=8C36ACA4-E947-4760-9B05-93CAC04C6F87&amp;amp;displaylang=en"&gt;Beta available now&lt;/A&gt;), I plan to discuss some of the new graphics features that are coming into WPF in this release. There are a number of great new additions as well as improvements on existing features, but I will say that the one that I’m the most excited about is GPU-accelerated custom effects. I’m going to go into a good amount of depth &lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/09/a-series-on-gpu-based-effects-for-wpf.aspx"&gt;in a series&lt;/A&gt; of upcoming blog posts, so I’ll dedicate this one to talking about the basics of what we’re offering and the motivation behind the feature.&lt;/P&gt;
&lt;P&gt;One of the hallmarks of WPF is the ability to mix and match media types, to compose visual elements, and to give the developer a substantial amount of freedom in the way they construct the interfaces for their applications. However, they are typically restricted to using the building blocks that WPF provides, such as rectangles, text, video, paths, gradients, images, etc. As rich as that set of primitives is, it is still a fixed set of primitives that only has the ability to grow as new releases of WPF come out. At the same time, the graphics processing unit (GPU) is becoming ever more powerful and ever more flexible. These two facts are somewhat at odds with each other, and this post talks about ways we bridge the gap by providing for GPU-accelerated custom effects (which I’ll just shorten to “Effects” from this point on).&lt;/P&gt;
&lt;P&gt;With Effects, you can harness the programmability of the GPU and still benefit from all the power of animation, data binding, element composition and media integration that WPF offers. Moreover, 3&lt;SUP&gt;rd&lt;/SUP&gt; parties can offer very powerful libraries of Effects that other developers using WPF can just use without needing to understand anything about GPU programming.&lt;/P&gt;
&lt;H3&gt;Applying motion blur to a scrolling list&lt;/H3&gt;
&lt;P&gt;As an initial example to see the sorts of power and flexibility one has with Effects, consider this UI:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_12.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_12.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=103 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_2.png" width=616 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_2.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The "film strip" at the top can be scrolled through.&amp;nbsp; Effects have been used as part of this film strip control so that when you move quickly through them, a "motion blur" effect gets applied, slowing down as you come to rest.&amp;nbsp; Here's a resultant snapshot of that:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_14.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_14.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=104 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_5.png" width=616 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_5.png"&gt;&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The rest of this post will look at a simpler example for explanatory purposes.&lt;/P&gt;
&lt;H3&gt;A simple example of using a built-in Effect&lt;/H3&gt;
&lt;P&gt;As a first simple example, we'll use the built in DropShadow Effect to make this Button:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_11.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_11.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=128 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_thumb_4.png" width=226 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_thumb_4.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;look like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_9.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_9.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=131 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_thumb_3.png" width=229 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/SampleDraft_8054/image_thumb_3.png"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;To do this, all we do is add an Effect property to our button:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt; &amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;DropShadowEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Hello
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;This Effect uses the built-in "DropShadowEffect".&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;H3&gt;A simple example of using a custom Effect&lt;/H3&gt;
&lt;P&gt;Using a custom Effect is really identical to using a built-in Effect.&lt;/P&gt;
&lt;P&gt;The following is a simple semi-transparent Button and TextBox and an Image placed inside of a Grid.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_2.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_2.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=278 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb.png" width=364 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;The XAML for the above is roughly this (I’ve removed properties of Image and Button and TextBox that just aren’t relevant to this discussion):&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;  &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;  /&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
  &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;What I’ll do now is apply a very simple Effect called ColorComplementEffect that’s part of a custom assembly I’ve created. All we do is this: &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;  &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
        &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;ColorComplementEffect &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;/&amp;gt;
    &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid.Effect&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;

    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Image &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;...&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;  /&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Button &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
    &amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;TextBox &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;... /&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;
  &amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;Grid&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P class=MsoNormal style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: normal; mso-layout-grid-align: none"&gt;What we’ve done is established the Effect property on the Grid, and set it to an instance of ColorComplementEffect. Note the “eff:” namespace on this… this indicates my custom assembly, and I need to add the following xmlns declaration to ensure this is found in the namespace MyEffects in the custom assembly MyEffects.dll:&lt;/P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: red"&gt;xmlns&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;eff&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="clr-namespace:MyEffects;assembly=MyEffects"&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;ColorComplementEffect, for every pixel in the element it’s being attached to, outputs the complement of that pixel (that is, 1.0 - val, for each of the RGB components of the element). The result looks like this:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_6.png" mce_href="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_6.png"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=278 alt=image src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_1.png" width=364 border=0 mce_src="http://blogs.msdn.com/blogfiles/greg_schechter/WindowsLiveWriter/GPUacceleratedcustomeffectsforWPF_AD74/image_thumb_1.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;Note how the button and text box are still present and remain interactive, just with the colors complemented (which makes it look like a photographic negative).&lt;/P&gt;
&lt;P&gt;(A later post will show how to create Effects like ColorComplementEffect, here we just discuss using them.)&lt;/P&gt;
&lt;H3&gt;What’s happening here?&lt;/H3&gt;
&lt;P&gt;So what’s a good way to think about what we just did above? The Effects that can be written will operate on pixels, and (roughly) will take bitmaps in (which are just arrays of pixels) and for each pixel that it needs to output, the Effect will generate a color. Yet we applied the Effect to, in the above case, a Grid with multiple children, which we know isn’t a bitmap.&lt;/P&gt;
&lt;P&gt;What’s happening is that WPF sees that an Effect is applied to a UIElement, and rasterizes the UIElement at the proper size into a bitmap, and then applies the Effect. Thus, Effects can be applied to &lt;I&gt;any&lt;/I&gt; UIElement (or Visual, for that matter). This includes video, and some of the more impactful uses apply Effects to video.&lt;/P&gt;
&lt;H3&gt;What can I do with these?&lt;/H3&gt;
&lt;P&gt;It’s the possibilities that GPU-accelerated Effects unlock that have me so excited about this addition. Basically, at GPU processing speeds, applications can apply effects that do, for instance:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Color modification: channel separation, tinting, saturation, contrast, monochrome, toning, thresholding, pixellation, bloom, chromakey, etc. &lt;/LI&gt;
&lt;LI&gt;Displacement effects: swirl, motion blur, ripples, pixellation, sharpen, pinch, bulge, etc. &lt;/LI&gt;
&lt;LI&gt;Generative effects: algorithmic generation of interesting texture patterns, fractals, etc. &lt;/LI&gt;
&lt;LI&gt;Multiple-input effects: blending, masking, storing computational results in textures, etc. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;But, the most exciting thing about all of this is that the above are just a small sampling of possibilities we’ve discussed in the team. What we’re certain of is that folks in the WPF community can and are going to be creating Effects that we would have never anticipated and will just blow everyone away.&lt;/P&gt;
&lt;H3&gt;What are these Effects?&lt;/H3&gt;
&lt;P&gt;While we don’t discuss the specifics of writing Effects in this posting (later posts will do so at length), we do describe what they are. Let me first describe how one programs a GPU, independent of WPF:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;GPU’s are fundamentally &lt;A href="http://en.wikipedia.org/wiki/SIMD" mce_href="http://en.wikipedia.org/wiki/SIMD"&gt;SIMD&lt;/A&gt; processors, able to operate on a very large number of pixels in parallel. A class of GPU “program” called a “pixel shader” (or a “fragment shader”) is basically a program that will execute on each and every pixel it outputs. &lt;/LI&gt;
&lt;LI&gt;In the Microsoft ecosystem, GPUs are programmed and controlled through DirectX. You download a GPU “program” into the GPU through DirectX, and you use DirectX to invoke that program. &lt;/LI&gt;
&lt;LI&gt;There is a GPU assembly language that the GPU’s operate on. There is also a &lt;A href="http://msdn.microsoft.com/en-us/library/bb509561(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/bb509561(VS.85).aspx"&gt;higher-level language called HLSL&lt;/A&gt; that is part of DirectX. DirectX provides a compiler to compile the HLSL down into GPU assembly code. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Given this, an Effect is two things:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A compiled HLSL (or assembly) pixel shader with shader constants used to represent variable inputs from the application. &lt;/LI&gt;
&lt;LI&gt;A .NET class that declares contains the pixel shader, and exposes WPF DependencyProperties that are bound to the shader constants used in the pixel shader. This allows modification of properties and parameters of shaders in the exact same way that properties of other WPF entities are manipulating (including support for animation and databinding of these properties and parameters). &lt;/LI&gt;&lt;/UL&gt;
&lt;H3&gt;But isn’t writing HLSL hard?&lt;/H3&gt;
&lt;P&gt;Aspects of writing HLSL can be tricky, particularly adapting to the SIMD mindset and the limit to the number of instructions that can be executed.&lt;/P&gt;
&lt;P&gt;In a way, though, the question is missing the point. Our expectation is that there will be many, many consumers of Effects (app developers as well as component developers who just want to use an Effect). Consuming an Effect, as the example above shows, is identical to consuming any other custom-written WPF control or library component. There will be fewer creators of Effects, just because the bar is somewhat higher, requiring an understanding of HLSL. However, we do expect/hope even that number to be pretty high, just because the Effects written can be very highly leveraged by users of the WPF system.&lt;/P&gt;
&lt;P&gt;That’s it for this initial post on Effects. Lots more goodness to come in subsequent posts.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8480839" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/Effects/default.aspx">Effects</category></item><item><title>A Series on GPU-based Effects for WPF</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/05/12/a-series-on-gpu-based-effects-for-wpf.aspx</link><pubDate>Mon, 12 May 2008 17:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8480821</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>19</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/8480821.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=8480821</wfw:commentRss><description>&lt;P&gt;GPU-based Effects are a hot new feature in WPF for .NET 3.5 SP1.&amp;nbsp; I'm going to be blogging a series of articles with progressively more detailed information in them, and am using &lt;EM&gt;this&lt;/EM&gt; post as a place to store a table of contents of these posts.&amp;nbsp; Here's what's out there so far:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/gpu-accelerated-custom-effects-for-wpf.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/gpu-accelerated-custom-effects-for-wpf.aspx"&gt;GPU-accelerated custom Effects for WPF&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/using-effect-in-wpf-part-2.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/using-effect-in-wpf-part-2.aspx"&gt;Using Effects in WPF (Part 2)&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/more-details-on-how-effects-work.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/more-details-on-how-effects-work.aspx"&gt;More details on how Effects work&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/05/12/introduction-to-writing-effects.aspx"&gt;Writing custom GPU-based Effects for WPF&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A title="A simple Effect sample project and ClickOnce application" href="http://blogs.msdn.com/greg_schechter/archive/2008/05/13/a-simple-effect-sample-project-and-clickonce-application.aspx"&gt;A simple Effect sample project and ClickOnce application&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://blogs.msdn.com/greg_schechter/archive/2008/05/15/writing-custom-effects-adding-parameters-to-effects.aspx"&gt;Writing custom Effects - adding parameters to Effects&lt;/A&gt; &lt;/LI&gt;
&lt;LI&gt;&lt;A title="A VisualStudio BuildTask and project and item templates for writing ShaderEffects" href="http://blogs.msdn.com/greg_schechter/archive/2008/08/11/a-visualstudio-buildtask-and-project-and-item-templates-for-writing-shadereffects.aspx"&gt;A VisualStudio BuildTask and project and item templates for writing ShaderEffects&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/greg_schechter/archive/2008/09/16/introducing-multi-input-shader-effects.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/09/16/introducing-multi-input-shader-effects.aspx"&gt;Introducing Multi-Input Shader Effects&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A class="" href="http://blogs.msdn.com/greg_schechter/archive/2008/09/27/a-more-useful-multi-input-effect.aspx" mce_href="http://blogs.msdn.com/greg_schechter/archive/2008/09/27/a-more-useful-multi-input-effect.aspx"&gt;A More Useful Multi-Input Effect&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8480821" width="1" height="1"&gt;</description></item><item><title>VB.NET version of Planerator posted</title><link>http://blogs.msdn.com/greg_schechter/archive/2008/02/10/vb-net-version-of-planerator-posted.aspx</link><pubDate>Mon, 11 Feb 2008 05:08:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7601068</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/7601068.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=7601068</wfw:commentRss><description>&lt;p&gt;Sean Cullinan, of &lt;a href="http://www.blendblog.net/"&gt;blendblog.net&lt;/a&gt;, recently &lt;a href="http://www.blendblog.net/Blendblognet/tabid/36/EntryID/30/Default.aspx"&gt;posted a VB.NET port&lt;/a&gt; of the &lt;a href="http://blogs.msdn.com/greg_schechter/archive/2007/10/26/enter-the-planerator-dead-simple-3d-in-wpf-with-a-stupid-name.aspx"&gt;Planerator&lt;/a&gt;.&amp;#160; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7601068" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category></item><item><title>Some implementation details of the Planerator</title><link>http://blogs.msdn.com/greg_schechter/archive/2007/11/28/some-implementation-details-of-the-planerator.aspx</link><pubDate>Wed, 28 Nov 2007 09:31:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6574085</guid><dc:creator>Greg Schechter</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/greg_schechter/comments/6574085.aspx</comments><wfw:commentRss>http://blogs.msdn.com/greg_schechter/commentrss.aspx?PostID=6574085</wfw:commentRss><description>&lt;p&gt;My previous two posts (&lt;a href="http://blogs.msdn.com/greg_schechter/archive/2007/10/26/enter-the-planerator-dead-simple-3d-in-wpf-with-a-stupid-name.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/greg_schechter/archive/2007/11/28/planerator-comments-and-posted-xbap.aspx"&gt;here&lt;/a&gt;) discuss usage of the Planerator control.&amp;#xA0; There are some unique issues that needed to be resolved in the implementation that WPF geeks might be interested in.&amp;#xA0; If you just are interested in using it, and not finding out how the sausage is made, you might want to just skip this.&lt;/p&gt;  &lt;p&gt;Actually, though, the sausage-making in this case is pretty nice, and the Planerator implementation is quite clean.&amp;#xA0; It's contained in about 280 lines of C# code in Planerator.cs.&amp;#xA0; There are some tricky aspects, though. Below are the salient points.&lt;/p&gt;  &lt;h3&gt;Interactive Content on 3D&lt;/h3&gt;  &lt;p&gt;One of the new features in WPF 3.5 is Viewport2DVisual3D, which is a way of getting a UIElement in as a material in 3D, and yet have it remain interactive.&amp;#xA0; This is used in the Planerator for the front face of the plane.&amp;#xA0; The back face of the plane just uses a VisualBrush for its material, and thus isn't interactive. &lt;/p&gt;  &lt;h3&gt;Caching of brush realizations&lt;/h3&gt;  &lt;p&gt;One critical performance optimization that the developer must opt into is to allow caching of the bitmaps that result from rasterizing a VisualBrush or Viewport2DVisual3D.&amp;#xA0; Without doing this, each frame renders the material anew, which can be quite expensive.&amp;#xA0; There are static methods off of RenderOptions that control caching in WPF.&amp;#xA0; In Planerator.cs, these are called from the &amp;quot;SetCachingForObject&amp;quot; private method.&lt;/p&gt;  &lt;h3&gt;Layout invalidation&lt;/h3&gt;  &lt;p&gt;When the contents of the Planerator change internally resulting in layout changes to those contents (for instance, a Label in a horizontal StackPanel gets longer, making the entire content wider), then the Planerator itself should be remeasured.&amp;#xA0; This, though, poses a problem because the contents are embedded in a Viewport2DVisual3D, and layout doesn't flow in and out of that.&amp;#xA0; &lt;/p&gt;  &lt;p&gt;The solution pursued here is that when we set up the Planerator, we wrap the child in a custom Decorator defined in the project and called LayoutInvalidationCatcher.&amp;#xA0; LayoutInvalidationCatcher overrides MeasureOverride and ArrangeOverride, and results in invalidating the Planerator instance's measure and arrange, respectively, thus forcing the Planerator to be re-laid out, and getting the results we want.&lt;/p&gt;  &lt;h3&gt;Databinding passthrough&lt;/h3&gt;  &lt;p&gt;A problem similar to the Layout Invalidation problem above is with databinding.&amp;#xA0; Because the children are embedded in Viewport2DVisual3D, databinding processing doesn't flow into it.&amp;#xA0; Therefore, we make the logical child of the Planerator be the content itself, while the visual child is the 3D construct that get built up, including the use of Viewport2DVisual3D.&amp;#xA0; By doing this, we allow databinding to flow to the Planerator's child properly, through the logical tree.&amp;#xA0; Then everything is set up to render it as part of the visual tree.&lt;/p&gt;  &lt;h3&gt;Proper sizing&lt;/h3&gt;  &lt;p&gt;Finally, a key aspect to making Planerator meaningful and friction-free is that it sizes itself precisely to the size of the underlying content, as if the Planerator just weren't there (at least until you start changing the rotation angles).&amp;#xA0; There are two relevant pieces to this.&amp;#xA0; One is camera setup, and this is described in detail in &lt;a href="http://blogs.msdn.com/greg_schechter/archive/2007/04/03/camera-construction-in-parallaxui.aspx"&gt;this previous post&lt;/a&gt; of mine.&amp;#xA0; &lt;/p&gt;  &lt;p&gt;The second is in determining the proper size of the child element itself.&amp;#xA0; It's not sufficient to use the results of Measure(), since those aren't the &amp;quot;ink bounds&amp;quot;... that is, it includes whitespace that doesn't get rendered to because, for instance, a Canvas is made explicitly wider than all the stuff that renders into it.&amp;#xA0; This is problematic because when such a visual is applied as a VisualBrush (or as Viewport2DVisual3D) it just uses the rendered bounds of the Visual, and thus the result would be distorted if we used Measure() results.&amp;#xA0; Thus, in order to get the correct &amp;quot;ink bounds&amp;quot;, we use VisualTreeHelper.GetDescendantBounds().&lt;/p&gt;  &lt;p&gt;&amp;#xA0;&lt;/p&gt;  &lt;p&gt;Put all those together, and you get a pretty cool Planerator control.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6574085" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/greg_schechter/archive/tags/WPF/default.aspx">WPF</category></item></channel></rss>