13,558,412 members
Tip/Trick
alternative version

Stats

11.9K views
10 bookmarked
Posted 27 May 2012
Licenced CPOL

, 27 May 2012
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.

Share

 Software Developer (Senior) Egypt
DotNet developer

Graphics researches and GPU Acceleration Developer.

Full stack web developer.

Bachelor's degree of Medicine and Surgery.

You may also be interested in...

 First Prev Next
 tilt.fx fixed chrislai00004-May-16 22:17 chrislai0000 4-May-16 22:17
 Re: tilt.fx fixed Greg Mulvihill30-Nov-17 5:48 Greg Mulvihill 30-Nov-17 5:48