13 תגובות

[This blog was migrated. You will not be able to comment here.The new URL of this post is http://khason.net/blog/hlsl-pixel-shader-effects-tutorial/]

Recently, I already wrote about PixelShader effects, introduced in .NET framework 3.5 SP1 (WPF). However it looks like for most people this syntax is still hard to understand. Today we’ll try to lean it more. In order to do this, I wrote small program, that helps you to write and debug pixel shader effects quickly. This how it looks like

Hit Open to load image, Write your code and hit Execute to compile and apply bitmap dx effect to the image. Let’s start from very beginning. Effect, that does nothing:

sampler2D input : register(s0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 Color;
Color = tex2D( input , uv.xy);
return Color;
}

This is the results:

What was done? We got pixel. Read it color and return it as it to the shader. Let’s do something more interesting.

Actually we can get float2 as coordinate, this means, that it can be spitted to uv.x and uv.y. Also color is float4 (argb), thus we can change color. Let’s multiply color by 3

Color = tex2D( input , uv.xy)*3;

And the result is bright image

We also can make operations with variables.

Color = tex2D( input , uv.xy)*uv.x;

Result

We not have to change whole color. We can also change only its part. Blue for example

Color = tex2D( input , uv.xy);
Color.b = Color.b*2;

Result

Or execute math operations

Color = tex2D( input , uv.xy);
Color.r = Color.r*sin(uv.x*100)*2;
Color.g = Color.g*cos(uv.x*150)*2;
Color.b = Color.b*sin(uv.x*50)*2;

Result

Color is not only thing we can operate. Actually we’re sampling coordinates, so operations done with coordinates should work. Let’s try to stretch image

uv.x = uv.x * 0.5;
Color = tex2D( input , uv.xy);

Result

Why 0.5? Should not it make it smaller? Actually not, you’re multiplying coordinates, so to make the image smaller, you should divide

uv.x = uv.x / 0.5;
Color = tex2D( input , uv.xy);

Result

Some math could be fun here also

uv.y = uv.y  + (sin(uv.y*100)*0.03);
Color = tex2D( input , uv.xy);

Result

There are a ton of interesting effects you can do by using pixel shaders. Here for example color shift

Color = tex2D( input , uv);
Color.r -= tex2D( input , uv +(somevar/100)).r;
Color.g += tex2D( input , uv+ (somevar/200)).g;
Color.b -= tex2D( input , uv+ (somevar/300)).b;

Result:

Or, even cooler efects

Color -= tex2D(input , uv.xy-0.003)*2.7f;
Color += tex2D( input , uv.xy+0.003)*2.7f;
Color.rgb = (Color.r+Color.g+Color.b)/3.0f;

Result

You can also use cases and ifs for even cooler effects

Color.rgb = (Color.r+Color.g+Color.b)/3.0f;
if (Color.r<0.2 || Color.r>0.9) Color.r = 0; else Color.r = 1.0f;
if (Color.g<0.2 || Color.g>0.9) Color.g = 0; else Color.g = 1.0f;
if (Color.b<0.2 || Color.b>0.9) Color.b = 0; else Color.b = 1.0f;

Result

Other words, the sky is the limit.

Please note, that Pixel Shaders done in GPU only, thus it is the most efficient method to manipulate your images. Actually, you can apply effect to any UIElement, thus the sky is really the limit.

Have a nice day and be good people. Download code for this article. Notice, that you’ll need DirectX SDK to compile pixel shader files and use this program

הוסף תגובה

13 תגובות

1. Joe18 ביוני 2008 ב 0:12

Thanks for the tutorial.
Your last comment – comparing WPF to flash – do you know if Flash 10 uses GPU only filters?

הגב
2. Tamir Khason18 ביוני 2008 ב 10:38

Joe, I did not compares Flash and WPF performance, so I do not know if Flash knows to apply pixel shaders

הגב
3. :)18 ביוני 2008 ב 19:27

Where are the docs for .NET 3.5 Sp1

הגב
4. Simon19 ביוני 2008 ב 1:30

Great post! The best post on WPF and Pixelshader i´ve seen so far!

הגב
5. :)19 ביוני 2008 ב 13:45

Why do you precompile the shaders? Is it possible to load and compile them at run-time?

הגב
6. Tamir Khason19 ביוני 2008 ב 15:12

Yes, you should compile shaders for 3.5 sp1.

הגב
7. Rakesh Ravuri24 ביולי 2008 ב 23:26

Thanks for the tool really helps in experimenting witn new ShaderEffects

הגב
8. Rakesh Ravuri11 באוגוסט 2008 ב 22:57

Tamir, based on the initial code from HLSLTester i wrote a application ShaderPad with support for animated input values and Texture inputs, check it out at http://www.codeplex.com/ShaderPad

הגב
9. kid25 בספטמבר 2008 ב 10:50

Could not get the example to work.

It builds and runs but when executing code in the first example I get…

The system cannot find the file specified

Pointing at line 62 of Window1.xaml.cs

???

הגב
10. Pestilence9 באוקטובר 2008 ב 9:32

Same Problem.

Error in Line 62. Win32Exception that the system cannot find the file pointing at "Process p = Process.Start(psi)"

הגב
11. Pestilence9 באוקטובר 2008 ב 10:46

OK fixed this myself. The fxc.exe of the DirectX SDK was missing in the debug directory.

הגב
12. Javaman4 בנובמבר 2008 ב 15:19

Pretty bad app . No error messages, none editing features.

הגב
13. Rob28 בנובמבר 2008 ב 15:44

Hi Tamir/guys , you dont need to go re-inventing the wheel for the shader developer apps…

http://rob.runtothehills.org/archives/180

I also did a full tutorial on code project using FX composer. ATI also has a comparable package, just incase you're an ATI lover 🙂
I'll shortly be updating the project to use 3.5sp1, now my current contract has finished! . Whew. Spare time at last 😉
Enjoy!

הגב
﻿