Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WPF Tilt Shader Effect

0.00/5 (No votes)
27 May 2012 2  
Non affine transform for WPF without 3D.

Introduction

The non affine transform is available now in WPF with the tilt shader effect. If you are interested in writing pixel shader effects in WPF or DirectX, you will be very interested in this article.

Background

First I imagined that the effect was easy and small operations can be made but technically while working with the shader kernel, I found some limits of pixel shade 2 when running on WPF 3.5 sp1 and that was a very bad thing.

After a few months I started again to search for a solution and I found the trick.

The Effect

The Effect is based on transforming a rectangle (the Visual layout rectangle) by its 4 corners. Because of PixelShader2 limits, the Effect is divided into two parts:

Part 1: Running on CPU (normal VB.NET code). This part involves converting input points and transforming it to be usable by the shader effect.

The TiltEffect class has nine dependency properties

  • 1 for the InputProperty
  • 4 for the Pixel Shader Handlers of the transformed points
  • 4 for the public layout of the points used by the user

Part 2 is running on GPU (shader effect). This part involves calculating the transformation of the tilt effect. The trick of this effect is to calculate the result point in two steps. First calculate the "Y" value of the point and then calculate the "X" value of the result point. The transformation of the points on the CPU first will decrease heavy load from the GPU and thus the Effect will work.

Description

The four points pt1, pt2, pt3, pt4 can be changed by the user and the TiltEffect class has to compute the p1, p2, p3, p4 points. The x and y values of the p1, p2, p3, p4 points have no relation because they are computed this way (p1 as example):

slope of (a - pt1) = slope of (pt1 - pt2) 
(a.y- pt1.y) / (a.x-pt1.x) = ( (pt1.y -pt2.y)/(pt1.x- pt2.x) ) 
(a.y- pt1.y) = ( (pt1.y -pt2.y)/(pt1.x- pt2.x) )/(a.x-pt1.x) 

a.y =[ ( (pt1.y -pt2.y)/(pt1.x- pt2.x) )/(a.x-pt1.x) ] +pt1.y 
the value of a.x = 0 
a.y =[ ( (pt1.y -pt2.y)/(pt1.x- pt2.x) )/(0-pt1.x) ] +pt1.y 
p1.y = a.y

slope of (b - pt1 ) = slope of ( pt1 - pt3 ) 
(b.y - pt1.y )/(b.x - pt1.x ) = (pt1.y - pt3.y)/(pt1.x - pt3.x )
(b.x - pt1.x ) /(b.y - pt1.y ) = (pt1.x - pt3.x ) / (pt1.y - pt3.y)
(b.x - pt1.x ) =( (pt1.x - pt3.x ) / (pt1.y - pt3.y) ) /(b.y - pt1.y ) 
b.x =[( (pt1.x - pt3.x ) / (pt1.y - pt3.y) ) /(b.y - pt1.y ) ] + pt1.x
the value of b.y = 0 
b.x =[( (pt1.x - pt3.x ) / (pt1.y - pt3.y) ) /(0 - pt1.y ) ] + pt1.x 
p1.x = b.x

And then calculate p2, p3, p4 points the same way.

On the GPU

The 4 registers pt1, pt2, pt3, pt4 resemble the p1, p2, p3, p4 properties in the TiltEffect class.

w1 = pt1.y + (pt2.y-pt1.y) * uv.x;
w2 = pt3.y+ (pt4.y- pt3.y) * uv.x;
maxy = w2 - w1;
cury = (uv.y - w1)/maxy;

This algorithm retrieves the Y value of the result point to be rendered in uv position and also curx is calculated by this algorithm separately.

Finally, trimming the results and returning the result color from the input texture.

But why this hard way?

The pixel shader limited arithmetic operations count.

Using the code

WPF 3.5 sp1 provides a very nice property named "Effect" for visual objects. This property can be used for making special effects on pixels of a specified visual.

Points of Interest

While playing with GPU you can make awesome Effects. Use your mind and release your imagination to get the most of your mind and to learn faster.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here