Pixel Shader Based Translation
Best animation performance in Silverlight 4 is obtained from the combination of procedural animation and a pixel shader, as reported in a previous blog. I know, a pixel shader is not really meant to be used for spatial manipulation. However, in Silverlight 4 vertex and geometry shaders are not available. Also, pixel shaders are limited to Model 2 shaders, and only limited data exchange is possible. The question is then, “how far can we push pixel shaders model 2” Another previous blog post discussed a preliminary version of dispersion, which is fairly complicated. This post is about translation. Translation means here that the coordinates in the 2-dimensional plane of a reduced image, in this case a video, are changed.
The Pixel Shader
The pixel shader was created using Shazzam. The first step is to reduce the image within its drawing surface, thus creating the room required for translation. Translation is in fact just changing the coordinates of the reduced images while correcting for the change in coordinates when sampling the source texture.
The pixel shader below, the if statement does the filtering. Left and Right are parameterized offset and cutoff values. The offset ‘Left’ is also used to correct for the displacement in sampling. Sampling is done by the ‘tex2d’ function.
sampler2D input : register(s0); // new HLSL shader /// <summary>Reduces the image</summary> /// <minValue>0.01</minValue> /// <maxValue>1.0</maxValue> /// <defaultValue>0.33</defaultValue> float Scale : register(C0); /// <summary>Changes the coordinate of the reduced image along the X axis</summary> /// <minValue>0.0</minValue> /// <maxValue>1.0</maxValue> /// <defaultValue>0.5</defaultValue> float OriginX : register(C1); /// <summary>Changes the coordinate of the reduced image along the Y axis</summary> /// <minValue>0.0</minValue> /// <maxValue>1.0</maxValue> /// <defaultValue>0.5</defaultValue> float OriginY : register(C2); float4 main(float2 uv : TEXCOORD) : COLOR { float4 Background = {0.937f, 0.937f, 0.937f, 1.0f}; float2 Origin = {OriginX, OriginY}; // Reduce nr. of computations float halfScale = 0.5 * Scale; float2 Left = Origin - halfScale; float2 Right = Origin + halfScale; // Filter out texels that do not sample (the correct location) if (uv.x >= Left.x && uv.x <= Right.x && uv.y >= Left.y && uv.y <= Right.y) return tex2D(input, (uv - Left) / Scale); else return Background; }
Client Application
The above shader is used in an App that runs a video fragmant, and can be explored
at my App Shop. The application has controls for video surface reduction, translation along the X-axis, and translation along the Y-axis. The video used in the application is a fragment of “Big Buck Bunny”, an open source animated video, made using only open source software tools.
Animation
Each of the above controls can be animated independently. Animation is implemented suing Storyboards for the slider control values. Hence you‘ll see them slide during animation. I didn’t use procedural animation, since, as discussed in the aforementioned previous blog post, is hindered by the implementation of the MediaElement.
The App is configured to take advantage of GPU acceleration, where possible. It really needs that for smooth animation. Also the maximum frame rate has been raised to 1000.
Performance Statistics
The animations run at about 250 FPS on my pc. This requires both significant effort from both the GPU as from the CPU. The required memory reaches a little over 3.5Mb.