Telerik blogs

Last time I asked if you find the pixel shaders useful in WPF applications. There were a couple of answers giving links to online resources, but no one did actually say they use shaders or find any practical application. Most of the examples in the internet target transition effects and I currently can’t think of any other practical application. Why so? Well, transition effects are good way to veil long loading times without using WPF transitions/animations, i.e. without increasing the CPU load (assuming effects are hardware accelerated). Applying effects constantly, on the other hand, will require rendering the scene all the time, which will inevitably increase the CPU load. For line-of-business applications this, of course, is highly unwanted effect.

 

So, back to the transition effects, let me share one of my accomplishments with you:

Screenshots

And here is the code*:

sampler2D implicitInput : register(s0);

// Progress range [0; 1]
float progress : register(c0);

// TransitionRange [0; 1)
float transitionRange : register(c1);

// Center X, Y values range: [0; 1]
float centerX : register(c2);
float centerY : register(c3);

float4 ToGreyScale(float4 color) : COLOR;
float EvaluateProgress(float progress, float2 center);

float4 main(float2 uv : TEXCOORD) : COLOR
{
  float2 center = float2(centerX, centerY);
  float2 distanceVector = uv.xy - center;

  float totalProgress = progress * (1 + transitionRange);

  float p = EvaluateProgress(totalProgress, center);
  float p2 = EvaluateProgress(totalProgress - transitionRange, center);

  float distance = length(distanceVector);
  float4 originalColor = tex2D(implicitInput, uv);

  if (distance <= p2)
    return originalColor;

  if (distance > p)
    return float4(0, 0, 0, 0);

  float d = pow((distance - p2) / (p - p2), 2);

  return (1-d) * d * ToGreyScale(originalColor) + (1-d) * originalColor;
}

float EvaluateProgress(float progress, float2 center)
{
  float dist = max(length(center), length(center - float2(1, 1)));
  dist = max(dist, length(center - float2(1, 0)));
  dist = max(dist, length(center - float2(0, 1)));

  return progress * dist;
}

float4 ToGreyScale(float4 color) : COLOR
{
  color.rgb = dot(color.rgb, float3(0.3, 0.59, 0.11));
  return color;
}

 

* Since I use ShaderPad to write effects, the center X & Y values are split in two. Also some calculations can be extracted outside the shader (such as most of the code in the EvaluateProgress method).


Comments

Comments are disabled in preview mode.