HLSL (Pixel shader) effects tutorial

17 ביוני 2008

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

image

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:

image

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

image

We also can make operations with variables.

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

Result

image

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

image

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

image

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

image

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

image

Some math could be fun here also

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

Result

image

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:

image

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

image

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

image

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

הוסף תגובה
facebook linkedin twitter email

כתיבת תגובה

האימייל לא יוצג באתר. (*) שדות חובה מסומנים

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

    Used the shader snippet from this page to create a wave reflection effect..

    להגיב
  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!

    להגיב