Lately, I've found out how awesome Milkdrop actually is! I like it so much in fact that I've decided to create a few presets as a final work for my uni (graphical design).
So I started learning how to actually do these presets and it's going pretty well... But there are some things that I'm having problem to understand and I need you guys to help me out!
1. What is this UV thing in shaders? Is it like x, y coordinates on the screen? How can I imagine this?
2. How can I move my screen through shaders? I mean, exactly like using dx or dy, but without actually using those. Or better, can I just move certain colors like this?
The shaders operate on all pixels simultaneously, in other words the same code is executed for each pixel. The only way to discriminate between pixels is uv.
uv.xy is a predefined float2 variable that stores the screen position. (0;0) is top left, (1;1) is bottom right.
Before you get into that you need to understand the difference between warp and comp shader but I sense from your questions that I would have to start from Adam and Eve, and I am sick of that because most of the lads to whom I explained these things were never heard of again. I suggest you find out by trial and error and come back when you have more specific questions.
No offence, I am willing to help but I need to be convinced you are serious about that and won't piss off after a week as most others do.
Be assured that no offence is taken and I am actually very thankful that you even bothered to reply!
I guess there's no real way for me to prove my good intentions, but you have my word: if I won't finish this, they won't let me finish the school, so it's a pretty big motivation to do at least something :S
I've tried to learn this thing on my own, but the only guide concerning with winamp's pixel shaders I found is this one ( http://www.geisswerks.com/hosted/mil...authoring.html ). I've finished it whole already. It was awesome, but I feel that it's designated more for the people that actually have any experience with this kind of things... Which is, sadly, not my case :S (by the way, if anyone knows other links concerning with pixel shaders that could help me somehow, I would be extremely thankful!)
Well, at least I actually know the difference between warp and compostie shader, so there you go
Last edited by Mufanza; 11th January 2012 at 11:01.
Ok, here is something to think about. Come back when you have questions.
The attached scheme shows the principle. It may not be 100% correct but will suffice.
Primitives (waves and shapes such as dots, lines, circles etc.) feed to both the warp and the comp shader.
The warp shader output adds to the comp shader input.
Exclusively the warp shader can feed its output back to its input.
The comp shader output goes to the screen.
The shaders do not simply pass their input through to their output but must be told so. The output is defined by the float3 "ret", which contains three colour intensities red, green, blue. For instance ret = float3 (1,0,0,) results in a plain red output.
The difference to normal programming is that the same shader code is executed for all pixels simultaneously, and there is no way to address individual pixels. In the above example, all pixels would be red. Now in general we don't want a uniform colour but something more interesting, hence we need a way to tell the shader the position of the pixel on the xy-plane. This position is stored in the float2 uv_orig, and its distorted derivative uv (Note that the comp shader cannot access the distorted uv). In other words, uv has a specific x,y,-value for each pixel, and this is the ONLY way to discriminate between pixels. Without use of uv, you can ONLY get a uniform output over the whole screen !!!!
To get started, let's ignore the warp shader first and set its output to black. Make a preset with a few primitives, for instance via the menu "simple waveforms", or use the attached starter.milk.
The warp shader output is set to black
ret = tex2D (sampler_main,uv)*.0;
The comp shader:
ret = 0.2*tex2D(sampler_lichen,uv); //displays texture lichen.jpg
ret += tex2D (sampler_main,uv); //displays sampler_main
What happens here: tex2D is a 2D texture sampler. It delivers the colour of a 2D texture (here lichen.jpg) at a coordinate (here uv). The uv coordinate results in the whole picture being sampled (the picture is assumed to stretch from (0;0) to (1;1) ). If we used
float2 pos = float2 (0.1; 0.5);
ret = 0.2*tex2D(sampler_lichen, pos);
the whole screen would show the colour of texture lichen.jpg as it happens to be at the position (0.1; 0.5).
In the next line, we do the same sampling for sampler_main as "texture". sampler_main is the internal variable for the shader input. So we see the waves defined in the "simple waveforms" section.
You should now be able to understand what happens when you manipulate uv.
ret = 0.2*tex2D(sampler_lichen, 4*uv); //will compress the texture
ret = 0.2*tex2D(sampler_lichen, 0.2*uv); //stretches the texture
ret = 0.2*tex2D(sampler_lichen, uv + 0.5); //shifts the texture by 0.5 in x- and y-direction
Now we go back to the warp shader. Its output feeds back to the input. Change the code to
ret = tex2D (sampler_main,uv + 0.01)*.9;
See. We sample the warp output, shifted by 0.01 diagonally, and send it to the output. This repeats every frame, so we get the smeared trail. The multiplication by 0.9 causes a slow fade of brightness over time, otherwise the overlay of infinite copies would finally cause the whole screen to go red.
Now here is the point where zoom, rot etc. comes in. Instead of manipulating uv in the warp shader directly, we can do this in the per-frame or per-vertex section by the variables zoom, rot, warp, dx, dy etc. That is quite handy and easy to understand. Try it.
In the per-vertex section, we can even manipulate uv dependant on the screen position, e.g. rot = (dx-0.5) causes a clockwise rotation for the left half of the screen, and an anti-clockwise on the right hand.