WPF 3.5 Sp1 – Now I’m Trying to Write Pixel Shaders :-S

I’ve been quite content up until today to say “I can’t write Pixel Shaders” and “I don’t know what High Level Shader Language” is.

But I thought I’d have a crack at it. Turns out, it just looks like C whereas I expected it to look like assembly.

I read a bit from here;

http://blogs.microsoft.co.il/blogs/tamir/archive/2008/06/17/hlsl-pixel-shader-effects-tutorial.aspx

which is a great resource for starting and then I decided to give it a whirl.

Following this post and downloading the DirectX SDK led me to this masterpiece 😉

sampler2D input : register(s0);
float factor : register(c0);

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 Color = tex2D( input , uv.xy);

    Color.rgb = Color.rgb * abs(sin(uv.x * 3.14 * factor)) * abs(sin(uv.y * 3.14 * factor));

    return(Color);
}

lined up with this piece of C# brilliance 🙂

using System;
using System.Windows.Media.Effects;
using System.Windows;
using System.Windows.Media;

namespace ShaderEffects
{
  public class MikeEffect : ShaderEffect
  {
    private static PixelShader _pixelShader = new PixelShader()
    {
      UriSource = new Uri(@"pack://application:,,,/ShaderEffects;component/MikeEffect/MikeEffect.ps")
    };

    public MikeEffect()
    {
      PixelShader = _pixelShader;

      UpdateShaderValue(InputProperty);
      UpdateShaderValue(FactorProperty);
    }

    public static readonly DependencyProperty InputProperty =
      ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(MikeEffect), 0);

    public Brush Input
    {
      get { return (Brush)GetValue(InputProperty); }
      set { SetValue(InputProperty, value); }
    }

    public static readonly DependencyProperty FactorProperty =
      DependencyProperty.Register("Factor",
        typeof(double), typeof(MikeEffect), new UIPropertyMetadata(0.0, PixelShaderConstantCallback(0)));

    public double Factor
    {
      get { return (double)GetValue(FactorProperty); }
      set { SetValue(FactorProperty, value); }
    }
  }
}

Naturally, I’m joking about the “brilliance” of it – I still don’t have a clue what I’m doing but I was very impressed with how easy it was and how fast it ran when I used it and bound the Factor property to a slider as in;

    <Border
      Grid.ColumnSpan="2">
      <Border.Effect>
        <local:MikeEffect
          Factor="{Binding ElementName=mikeSlider,Path=Value}" />
      </Border.Effect>    

and then;

  <Slider
        Minimum="0"
        Maximum="20"
        Value="1"
        x:Name="mikeSlider"
        Width="192" />

I believe you can also do this with multi-input effects to transition from one piece of content to another – sounds pretty slick.