mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-09-24 15:54:12 +00:00
772 lines
47 KiB
HTML
772 lines
47 KiB
HTML
|
<HTML>
|
||
|
<A NAME="milkdrop_preset_authoring_top">
|
||
|
<PRE>
|
||
|
|
||
|
<B>MILKDROP preset authoring guide</B>
|
||
|
<A HREF="milkdrop.html">return to milkdrop.html</A>
|
||
|
|
||
|
|
||
|
|
||
|
* * *
|
||
|
Note that there is another, quite comprehensive, Preset Authoring Guide
|
||
|
available on the web at <A HREF="http://www.milkdrop.co.uk/">http://www.milkdrop.co.uk/</A>, which is continually
|
||
|
updated and expanded through the hard work of a few dedicated preset
|
||
|
authors. Whereas this guide (the one you are currently viewing) gives the bare
|
||
|
technical specifications for writing your own presets, the guide at milkdrop.co.uk
|
||
|
'starts at the beginning' and walks you through all of the mathematics and subtleties
|
||
|
of 'rolling your own', explaining things in great detail. The guide at milkdrop.co.uk
|
||
|
is very highly recommended to anyone who wishes to learn more about creating their
|
||
|
own presets.
|
||
|
* * *
|
||
|
|
||
|
|
||
|
<B>Section Listing</B>
|
||
|
-----------------------
|
||
|
1. <A HREF="#1">about presets</A>
|
||
|
2. <A HREF="#2">preset authoring - basic</A>
|
||
|
3. <A HREF="#3">preset authoring - advanced</A>
|
||
|
a. <A HREF="#3a">per-frame equations</A>
|
||
|
b. <A HREF="#3b">per-pixel equations</A>
|
||
|
c. <A HREF="#3c">preset initialization code and q1-q8</A>
|
||
|
d. <A HREF="#3d">custom shapes & waves</A>
|
||
|
e. <A HREF="#3e">quality assurance</A>
|
||
|
f. <A HREF="#3f">debugging</A>
|
||
|
g. <A HREF="#3g">function reference</A>
|
||
|
|
||
|
|
||
|
<A NAME="1">
|
||
|
<B>1. About Presets</B>
|
||
|
-----------------------
|
||
|
A 'preset' is a collection of parameters that tell MilkDrop how to
|
||
|
draw the wave, how to warp the image around, and so on. MilkDrop
|
||
|
ships with around ~100 built-in presets, each one having a distinct
|
||
|
look and feel to it.
|
||
|
|
||
|
Using MilkDrop's built-in "preset-editing menu", you can edit presets
|
||
|
on the fly, from within the program. You can make slight adjustments
|
||
|
to existing presets, then save over them; or you can change lots of
|
||
|
things, so the preset doesn't look anything like the original, and
|
||
|
then save it under a new name. You can even write insane new
|
||
|
mathematical equations, of your own imagination, into your preset
|
||
|
files and come up with things that MilkDrop has never done before!
|
||
|
|
||
|
Each preset is saved as a file with the ".milk" extension, so you can
|
||
|
easily send them to your friends or post them on the web. You can also
|
||
|
go to <A HREF="http://www.nullsoft.com/free/milkdrop">http://www.nullsoft.com/free/milkdrop</A> and then jump to the
|
||
|
"preset sharing forum" to see what other people have come up with,
|
||
|
or post your own cool, new presets.
|
||
|
|
||
|
|
||
|
<A NAME="2">
|
||
|
<B>2. Preset Authoring - Basic</B>
|
||
|
-----------------------
|
||
|
|
||
|
You can edit the properties of the current preset by hitting 'M',
|
||
|
which brings up the "preset-editing menu". From this menu you
|
||
|
can use the up and down arrow keys to select an item. Press
|
||
|
the RIGHT arrow key to move forward through the menu and select
|
||
|
the item (note: you can also hit SPACE or RETURN to do this);
|
||
|
***press the LEFT arrow key to go back to the previous menu.***
|
||
|
|
||
|
Pressing 'M' while the menu is already showing will hide the menu;
|
||
|
pressing ESCAPE will do the same thing. Press 'M' again to bring
|
||
|
the menu back.
|
||
|
|
||
|
Once you've reached an item on the menu whose value can be edited,
|
||
|
use the UP and DOWN arrow keys to increase or decrease its value,
|
||
|
respectively. Changes will register immediately. Use PAGE UP and
|
||
|
PAGE DOWN to increase the value more quickly. Hold down SHIFT
|
||
|
and use the UP/DOWN arrow keys to change the value very slowly.
|
||
|
Hit RETURN To keep the new value, or ESC to abort the change.
|
||
|
|
||
|
If the item you're editing is a text string, you can use the
|
||
|
arrow keys to move around. The Insert key can be used to toggle
|
||
|
between insert and overtype modes. You can hold shift and use
|
||
|
the arrow keys (home, end, left, right) to make a selection,
|
||
|
which will be identified by brackets []. You can then use CTRL-C
|
||
|
or CTRL-X to copy or cut text. CTRL-P pastes. When finished
|
||
|
editing, hit RETURN To keep the new string, or ESC to abort the
|
||
|
change.
|
||
|
|
||
|
You'll want to get into the habit of using SCROLL LOCK whenever
|
||
|
you're making changes to a preset that you intend to save;
|
||
|
otherwise, the preset is sure to keep randomly changing on you.
|
||
|
You might ask me, "why don't you just automatically lock the
|
||
|
preset while the menu is up?" I will answer you, "because in
|
||
|
the instant between exiting the menu and going to save the preset,
|
||
|
the preset might then switch, and you'd lose your changes." Then
|
||
|
you might ask me, "then why don't you just leave it locked
|
||
|
whenever the user makes a change from the menu?" and I will say
|
||
|
to you, "because I hate it when programs do things like that. You
|
||
|
have an idea in your brain about the state of the Scroll Lock key,
|
||
|
because you're the one setting that state. I want your mind to
|
||
|
always be up-to-date." And you might then ask me: "how large is
|
||
|
large?" And I will tell you: "thirty."
|
||
|
|
||
|
There are also some hotkeys that will allow you to change certain
|
||
|
common parameters to the current preset. These are listed below.
|
||
|
|
||
|
MOTION
|
||
|
i/I - zoom in/out
|
||
|
[ / ] - push motion to the left/right (dx)
|
||
|
{ / } - push motion up/down (dy)
|
||
|
< / > - rotate left/right (rot)
|
||
|
o/O - shrink/grow the amplitude of the warp effect
|
||
|
|
||
|
WAVEFORM
|
||
|
W - cycle through waveforms
|
||
|
j/J - scale waveform down/up
|
||
|
e/E - make the waveform more transparent/more solid
|
||
|
|
||
|
BRIGHTNESS
|
||
|
d/D - decrease, increase decay (fades image to black over time)
|
||
|
g/G - decrease, increase gamma (brightness)
|
||
|
|
||
|
VIDEO ECHO effect
|
||
|
q/Q - scale 2nd graphics layer down/up
|
||
|
a/A - decrease/increase alpha of 2nd graphics layer
|
||
|
F - flip 2nd graphics layer (cycles through 4 fixed orientations)
|
||
|
|
||
|
|
||
|
|
||
|
<A NAME="3">
|
||
|
<B>3. Preset Authoring - Advanced</B>
|
||
|
-----------------------
|
||
|
|
||
|
This section describes how to use the 'per-frame' and 'per-pixel'
|
||
|
equations to develop unique new presets.
|
||
|
|
||
|
|
||
|
<A NAME="3a">
|
||
|
<B>a. PER-FRAME EQUATIONS</B>
|
||
|
----------------------
|
||
|
|
||
|
When you hit 'm' to show the preset-editing menu, several items
|
||
|
show up. If you explore the sub-menus, you'll see that
|
||
|
all of the properties that make up the preset you're currently
|
||
|
viewing are there. The values you can specify here (such as
|
||
|
zoom amount, rotation amount, wave color, etc.) are all static
|
||
|
values, meaning that they don't change in time. For example,
|
||
|
take the 'zoom amount' option under the 'motion' submenu.
|
||
|
If this value is 1.0, there is no zoom. If the value is 1.01,
|
||
|
the image zooms in 1% every frame. If the value is 1.10, the
|
||
|
image zooms in 10% every frame. If the value is 0.9, the image
|
||
|
zooms out 10% every frame; and so on.
|
||
|
|
||
|
However, presets get far more interesting if you can take these
|
||
|
parameters (such as the zoom amount) and animate them (make them
|
||
|
change over time). For example, if you could take the 'zoom
|
||
|
amount' parameter and make it oscillate (vary) between 0.9 and
|
||
|
1.1 over time, the image would cyclically zoom in and out, in
|
||
|
time.
|
||
|
|
||
|
You can do this - by writing 'per-frame' and 'per-pixel'
|
||
|
equations. Let's start with 'per-frame' equations. These are
|
||
|
executed once per frame. So, if you were to type the following
|
||
|
equation in:
|
||
|
|
||
|
zoom = zoom + 0.1*sin(time);
|
||
|
|
||
|
...then the zoom amount would oscillate between 0.9 and 1.1
|
||
|
over time. (Recall from your geometry classes that sin()
|
||
|
returns a value between -1 and 1.) The equation says: "take
|
||
|
the static value of 'zoom', then replace it with that value,
|
||
|
plus some variation." This particular equation would oscillate
|
||
|
(cycle) every 6.28 seconds, since the sin() function's
|
||
|
period is 6.28 (PI*2) seconds. If you wanted it to make it
|
||
|
cycle every 2 seconds, you could use:
|
||
|
|
||
|
zoom = zoom + 0.1*sin(time*3.14);
|
||
|
|
||
|
Now, let's say you wanted to make the color of the waveform
|
||
|
(sound wave) that gets plotted on the screen vary through time.
|
||
|
The color is defined by three values, one for each of the main
|
||
|
color components (red, green, and blue), each in the range 0 to 1
|
||
|
(0 is dark, 1 is full intensity). You could use something like this:
|
||
|
|
||
|
wave_r = wave_r + 0.5*sin(time*1.13);
|
||
|
wave_g = wave_g + 0.5*sin(time*1.23);
|
||
|
wave_b = wave_b + 0.5*sin(time*1.33);
|
||
|
|
||
|
It's nice to stagger the frequencies (1.13, 1.23, and 1.33) of
|
||
|
the sine functions for the red, green, and blue color components
|
||
|
of the wave so that they cycle at different rates, to avoid them
|
||
|
always being all the same (which would create a greyscale wave).
|
||
|
|
||
|
Here is a full list of the variables available for writing per-frame
|
||
|
equations:
|
||
|
|
||
|
NAME WRITABLE? RANGE DESCRIPTION
|
||
|
---- --------- ----- -----------
|
||
|
zoom yes >0 controls inward/outward motion. 0.9=zoom out 10% per frame, 1.0=no zoom, 1.1=zoom in 10%
|
||
|
zoomexp yes >0 controls the curvature of the zoom; 1=normal
|
||
|
rot yes controls the amount of rotation. 0=none, 0.1=slightly right, -0.1=slightly clockwise, 0.1=CCW
|
||
|
warp yes >0 controls the magnitude of the warping; 0=none, 1=normal, 2=major warping...
|
||
|
cx yes 0..1 controls where the center of rotation and stretching is, horizontally. 0=left, 0.5=center, 1=right
|
||
|
cy yes 0..1 controls where the center of rotation and stretching is, vertically. 0=top, 0.5=center, 1=bottom
|
||
|
dx yes controls amount of constant horizontal motion; -0.01 = move left 1% per frame, 0=none, 0.01 = move right 1%
|
||
|
dy yes controls amount of constant vertical motion; -0.01 = move up 1% per frame, 0=none, 0.01 = move down 1%
|
||
|
sx yes >0 controls amount of constant horizontal stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1%
|
||
|
sy yes >0 controls amount of constant vertical stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1%
|
||
|
wave_mode yes 0,1,2,3,4,5,6,7 controls which of the 8 types of waveform is drawn
|
||
|
wave_x yes 0..1 position of the waveform: 0 = far left edge of screen, 0.5 = center, 1 = far right
|
||
|
wave_y yes 0..1 position of the waveform: 0 = very bottom of screen, 0.5 = center, 1 = top
|
||
|
wave_r yes 0..1 amount of red color in the wave (0..1),
|
||
|
wave_g yes 0..1 amount of green color in the wave (0..1)
|
||
|
wave_b yes 0..1 amount of blue color in the wave (0..1)
|
||
|
wave_a yes 0..1 opacity of the wave (0..1) [0=transparent, 1=opaque]
|
||
|
wave_mystery yes -1..1 what this parameter does is a mystery. (honestly, though, this value does different things for each waveform; for example, it could control angle at which the waveform was drawn.)
|
||
|
wave_usedots yes 0/1 if 1, the waveform is drawn as dots (instead of lines)
|
||
|
wave_thick yes 0/1 if 1, the waveform's lines (or dots) are drawn with double thickness
|
||
|
wave_additive yes 0/1 if 1, the wave is drawn additively, saturating the image at white
|
||
|
wave_brighten yes 0/1 if 1, all 3 r/g/b colors will be scaled up until at least one reaches 1.0
|
||
|
ob_size yes 0..0.5 thickness of the outer border drawn at the edges of the screen every frame
|
||
|
ob_r yes 0..1 amount of red color in the outer border
|
||
|
ob_g yes 0..1 amount of green color in the outer border
|
||
|
ob_b yes 0..1 amount of blue color in the outer border
|
||
|
ob_a yes 0..1 opacity of the outer border (0=transparent, 1=opaque)
|
||
|
ib_size yes 0..0.5 thickness of the inner border drawn at the edges of the screen every frame
|
||
|
ib_r yes 0..1 amount of red color in the inner border
|
||
|
ib_g yes 0..1 amount of green color in the inner border
|
||
|
ib_b yes 0..1 amount of blue color in the inner border
|
||
|
ib_a yes 0..1 opacity of the inner border (0=transparent, 1=opaque)
|
||
|
mv_r yes 0..1 amount of red color in the motion vectors
|
||
|
mv_g yes 0..1 amount of green color in the motion vectors
|
||
|
mv_b yes 0..1 amount of blue color in the motion vectors
|
||
|
mv_a yes 0..1 opacity of the motion vectors (0=transparent, 1=opaque)
|
||
|
mv_x yes 0..64 the number of motion vectors in the X direction
|
||
|
mv_y yes 0..48 the number of motion vectors in the Y direction
|
||
|
mv_l yes 0..5 the length of the motion vectors (0=no trail, 1=normal, 2=double...)
|
||
|
mv_dx yes -1..1 horizontal placement offset of the motion vectors
|
||
|
mv_dy yes -1..1 vertical placement offset of the motion vectors
|
||
|
decay yes 0..1 controls the eventual fade to black; 1=no fade, 0.9=strong fade, 0.98=recommended
|
||
|
gamma yes >0 controls display brightness; 1=normal, 2=double, 3=triple, etc.
|
||
|
echo_zoom yes >0 controls the size of the second graphics layer
|
||
|
echo_alpha yes >0 controls the opacity of the second graphics layer; 0=transparent (off), 0.5=half-mix, 1=opaque
|
||
|
echo_orient yes 0,1,2,3 selects an orientation for the second graphics layer. 0=normal, 1=flip on x, 2=flip on y, 3=flip on both
|
||
|
darken_center yes 0/1 if 1, help keeps the image from getting too bright by continually dimming the center point
|
||
|
wrap yes 0/1 sets whether or not screen elements can drift off of one side and onto the other
|
||
|
invert yes 0/1 inverts the colors in the image
|
||
|
brighten yes 0/1 brightens the darker parts of the image (nonlinear; square root filter)
|
||
|
darken yes 0/1 darkens the brighter parts of the image (nonlinear; squaring filter)
|
||
|
solarize yes 0/1 emphasizes mid-range colors
|
||
|
monitor yes any set this value for debugging your preset code; if you hit the 'N' key,
|
||
|
the value of 'monitor' will be posted in the upper-right corner of milkdrop.
|
||
|
for example, setting "monitor = q3;" would let you keep an eye on q3's value.
|
||
|
|
||
|
time NO >0 retrieves the current time, in seconds, since MilkDrop started running
|
||
|
fps NO >0 retrieves the current framerate, in frames per second.
|
||
|
frame NO retrieves the number of frames of animation elapsed since the program started
|
||
|
progress NO 0..1 progress through the current preset; if preset was just loaded, this is closer to 0; if preset is about to end, this is closer to 1.
|
||
|
-note that if Scroll Lock is on, 'progress' will freeze!
|
||
|
|
||
|
bass NO >0 retrieves the current amount of bass. 1 is normal; below ~0.7 is quiet; above ~1.3 is loud bass
|
||
|
mid NO >0 -same, but for mids (middle frequencies)
|
||
|
treb NO >0 -same, but for treble (high) frequencies
|
||
|
bass_att NO >0 retrieves an attenuated reading on the bass, meaning that it is damped in time and doesn't change so rapidly.
|
||
|
mid_att NO >0 -same, but for mids (middle frequencies)
|
||
|
treb_att NO >0 -same, but for treble (high) frequencies
|
||
|
|
||
|
meshx NO 8-128 tells you the user's mesh size in the X direction. always an integer value.
|
||
|
meshy NO 6-96 tells you the user's mesh size in the Y direction. always an integer value.
|
||
|
|
||
|
q1 yes any }
|
||
|
q2 yes any }
|
||
|
q3 yes any }
|
||
|
q4 yes any } Used to carry information between the per-frame code
|
||
|
q5 yes any } and the per-pixel code; see below.
|
||
|
q6 yes any }
|
||
|
q7 yes any }
|
||
|
q8 yes any }
|
||
|
|
||
|
|
||
|
Some of the variables are read-only, meaning that you shouldn't change
|
||
|
their values them through the equations. You can; it won't stop you;
|
||
|
but the results are unpredictable.
|
||
|
|
||
|
You can also make up to 30 of your own variables. For example:
|
||
|
|
||
|
my_volume = (bass + mid + treb)/3;
|
||
|
zoom = zoom + 0.1*(my_volume - 1);
|
||
|
|
||
|
This would make the zoom amount increase when the music is loud,
|
||
|
and decrease when the music is quiet.
|
||
|
|
||
|
HOWEVER, custom variables do not carry over from per-frame equations
|
||
|
to per-pixel equations; if you set a custom variable's value in the
|
||
|
per-frame equations, and try to read it in the per-pixel equations,
|
||
|
you will not get the correct value. Instead, you have to "bridge the
|
||
|
gap" using 8 special variables: q1 through q8. This is usually only
|
||
|
used when you want to precompute some custom values in the per-frame
|
||
|
equations for later use in the per-pixel equations. For a good
|
||
|
example of this, see the 'dynamic swirls' preset. See below for
|
||
|
more information on q1-q8.
|
||
|
|
||
|
|
||
|
|
||
|
<A NAME="3b">
|
||
|
<B>b. PER-PIXEL EQUATIONS</B>
|
||
|
-----------------------
|
||
|
|
||
|
So far we've discussed only how to change parameters based on
|
||
|
time. What if you wanted to also vary a parameter, such as the
|
||
|
zoom amount, in different ways, for different locations on the
|
||
|
screen? For example, normally, the result of the 'zoom' parameter
|
||
|
is to just do a flat zoom. This doesn't look very realistic,
|
||
|
because you don't see any perspective in the zoom. It would be
|
||
|
better if we could give a unique zoom amount to each pixel on
|
||
|
the screen; we could make the pixels far away from the center
|
||
|
zoom more, and this would give it more perspective. In order
|
||
|
to do this, we use "per-pixel" equations, instead of per-frame
|
||
|
equations.
|
||
|
|
||
|
The code for this per-pixel equation is simple:
|
||
|
|
||
|
zoom = zoom + rad*0.1;
|
||
|
|
||
|
Where 'rad' is the radius of the pixel if it were cast into
|
||
|
polar coordinates; from another perspective, 'rad' is the distance
|
||
|
of the pixel from the center of the screen. 'rad is zero at the
|
||
|
center, and 1 at the corners. So if we run the above code,
|
||
|
the image will be zoomed into 10% more at the edges of the screen
|
||
|
than at the center.
|
||
|
|
||
|
The per-pixel equations are really just like the per-frame equations,
|
||
|
except for a variables. The following variables are available
|
||
|
exclusively to per-pixel equations (and not to per-frame equations):
|
||
|
|
||
|
NAME WRITABLE? RANGE DESCRIPTION
|
||
|
---- --------- ----- -----------
|
||
|
x NO 0..1 retrieves the x-position of the current pixel. At the very left edge of the screen this would be 0; in the middle, 0.5; and at the right, 1.
|
||
|
y NO 0..1 retrieves the y-position of the current pixel. At the very top edge of the screen this would be 0; in the middle, 0.5; and at the bottom, 1.
|
||
|
rad NO 0..1 retrives the distance of the pixel from the center of the screen. At the center of the screen this will be zero, and at the corners, 1.
|
||
|
(The middle of the edges will be 0.707 (half of the square root of 2).
|
||
|
ang NO 0..6.28 retrieves the angle of the current pixel, with respect to the center of the screen.
|
||
|
If the point is to the right of the center, this is zero; above it, it is PI/2 (1.57); to the left, it is PI (3.14); and below, it is 4.71 (PI*3/2).
|
||
|
If it is just a dab below being directly to the right of the center of the screen, the value will approach 6.28 (PI*2).
|
||
|
(note: this is simply the arctangent of y over x, precomputed for you.)
|
||
|
|
||
|
zoom yes >0 controls inward/outward motion. 0.9=zoom out 10% per frame, 1.0=no zoom, 1.1=zoom in 10%
|
||
|
zoomexp yes >0 controls the curvature of the zoom; 1=normal
|
||
|
rot yes controls the amount of rotation. 0=none, 0.1=slightly right, -0.1=slightly clockwise, 0.1=CCW
|
||
|
warp yes >0 controls the magnitude of the warping; 0=none, 1=normal, 2=major warping...
|
||
|
cx yes 0..1 controls where the center of rotation and stretching is, horizontally. 0=left, 0.5=center, 1=right
|
||
|
cy yes 0..1 controls where the center of rotation and stretching is, vertically. 0=top, 0.5=center, 1=bottom
|
||
|
dx yes controls amount of constant horizontal motion; -0.01 = move left 1% per frame, 0=none, 0.01 = move right 1%
|
||
|
dy yes controls amount of constant vertical motion; -0.01 = move up 1% per frame, 0=none, 0.01 = move down 1%
|
||
|
sx yes >0 controls amount of constant horizontal stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1%
|
||
|
sy yes >0 controls amount of constant vertical stretching; 0.99=shrink 1%, 1=normal, 1.01=stretch 1%
|
||
|
|
||
|
time NO >0 retrieves the current time, in seconds, since MilkDrop started running
|
||
|
fps NO >0 retrieves the current framerate, in frames per second.
|
||
|
frame NO retrieves the number of frames of animation elapsed since the program started
|
||
|
progress NO 0..1 progress through the current preset; if preset was just loaded, this is closer to 0; if preset is about to end, this is closer to 1.
|
||
|
-note that if Scroll Lock is on, 'progress' will freeze!
|
||
|
|
||
|
bass NO >0 retrieves the current amount of bass. 1 is normal; below ~0.7 is quiet; above ~1.3 is loud bass
|
||
|
mid NO >0 -same, but for mids (middle frequencies)
|
||
|
treb NO >0 -same, but for treble (high) frequencies
|
||
|
bass_att NO >0 retrieves an attenuated reading on the bass, meaning that it is damped in time and doesn't change so rapidly.
|
||
|
mid_att NO >0 -same, but for mids (middle frequencies)
|
||
|
treb_att NO >0 -same, but for treble (high) frequencies
|
||
|
|
||
|
meshx NO 8-128 tells you the user's mesh size in the X direction. always an integer value.
|
||
|
meshy NO 6-96 tells you the user's mesh size in the Y direction. always an integer value.
|
||
|
|
||
|
q1 yes any }
|
||
|
q2 yes any }
|
||
|
q3 yes any }
|
||
|
q4 yes any } Used to carry information between the per-frame code
|
||
|
q5 yes any } and the per-pixel code; see below.
|
||
|
q6 yes any }
|
||
|
q7 yes any }
|
||
|
q8 yes any }
|
||
|
|
||
|
|
||
|
The main reason for distinction between per-frame and per-pixel equations
|
||
|
is simple: SPEED. If you have a per-pixel equation that doesn't make use
|
||
|
of the x, y, rad, or ang variables, then there's no reason for it to be
|
||
|
executed per-pixel; it could be executed once per frame, and the result
|
||
|
would be the same. So, here's a maxim to write on the wall:
|
||
|
|
||
|
"If a per-pixel equation doesn't use at least one of the variables
|
||
|
{ x, y, rad, ang }, then it should be actually be a per-frame
|
||
|
equation."
|
||
|
|
||
|
You might be wondering how on earth all these formulas could be computed
|
||
|
for every pixel on the screen, every frame, and still yield a high frame
|
||
|
rate. Well, that's the magic of the hamster. And the fact that it really
|
||
|
does the processing only at certain points on the screen, then interpolates
|
||
|
the results across the space between the points. In the config panel,
|
||
|
the "mesh size" option defines how many points (in X and Y) there are at
|
||
|
which the per-pixel equations are actually computed. When you crank this
|
||
|
option up, you start eating up CPU cycles rather quickly.
|
||
|
|
||
|
|
||
|
|
||
|
<A NAME="3c">
|
||
|
<B>c. PRESET INITIALIZATION CODE AND q1-q8</B>
|
||
|
-----------------------
|
||
|
In MilkDrop 1.03 and later, you can write code that is executed only
|
||
|
once, at the start of a preset. This code allows you to set the initial
|
||
|
value of your own (user-defined) variables (such as 'my_variable'), as well
|
||
|
as the q1..q8 variables. Any variable that is accessible in the per-frame
|
||
|
equations is also accessible here, <EM>for reading</EM>; however, most of them will not
|
||
|
be affected if you change them here, because they are overwritten by the base
|
||
|
variable values of the preset at the start of each frame! (i.e. the values
|
||
|
of the variables are reset to the values from the menus at the beginning of
|
||
|
each frame.) In effect, most of these variables are treated as 'read-only'
|
||
|
in the initialization code. If you do read (access) their values, you will
|
||
|
get the base values - the ones baked into the preset (via the menu system).
|
||
|
|
||
|
The variables that are <EM>writable</EM> include only q1..q8, and
|
||
|
<EM>any custom variables that you want to create & initialize for later use.</EM>
|
||
|
|
||
|
If you write to the values of q1..q8, these will become the new 'base values'
|
||
|
to which q1..q8 are initialized at the start of each frame, for the per-frame
|
||
|
code. So when you access (read) q1-q8 in the per-frame code, you'll get the
|
||
|
values that were set at the end of the preset init code. You can then
|
||
|
modify them (or not) in the per-frame code, and they will then be readable by
|
||
|
the per-pixel code; but they will not persist to the next frame; they will be
|
||
|
reset again, at the start of the next frame, to the values they had at the
|
||
|
end of the preset init code. <B>See the <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A> image for a diagram
|
||
|
of the flow of the values of the q1-q8 varibles.</B>
|
||
|
|
||
|
In the per-pixel code, the q1-q8 values start (for the first pixel in any frame)
|
||
|
as the values they had at the end of the per-frame code. If you modify q1-q8
|
||
|
in the per-pixel code, those modified values will carry over from pixel to
|
||
|
pixel. Next frame, they will be reset to whatever value they had at the end
|
||
|
of the [next frame's execution of the] per-frame code. (It's all in the diagram.)
|
||
|
|
||
|
If you declare & assign values to your own new variables here, however, these
|
||
|
values are 'sticky' like q1-q8; they can be modified by the per-frame code,
|
||
|
and they will retain their (modified) values from frame to frame.
|
||
|
|
||
|
One final note: when you edit the preset init code and apply it (by hitting
|
||
|
CTRL+ENTER), the init code will re-execute immediately. However, when you
|
||
|
edit the regular per-frame/per-pixel code and hit CTRL+ENTER, the preset init
|
||
|
code will NOT be re-executed; the results of the last execution will persist.
|
||
|
If you change per-frame/per-pixel code and want to re-execute the initialization
|
||
|
code (i.e. to randomize it or reset the preset), you'll have to save it and re-
|
||
|
load it.
|
||
|
|
||
|
|
||
|
|
||
|
<A NAME="3d">
|
||
|
<B>d. CUSTOM SHAPES AND WAVES</B>
|
||
|
----------------------
|
||
|
As of MilkDrop 1.04, two new features are available: custom shapes, and custom
|
||
|
waves. A preset can have up to 4 of each.
|
||
|
|
||
|
With custom shapes, you can draw an n-sided shape (with 3-100 sides) anywhere
|
||
|
on the screen, at any angle and size, in any color, and at any opacity. You
|
||
|
even have the option to map the previous frame's image onto the shape, which
|
||
|
makes for some incredible possibilities (such as realtime hardware fractals -
|
||
|
see the 'Geiss - Feedback' preset). You can also write per-frame code to
|
||
|
control all of these things about the shape(s). This way, they can react to
|
||
|
the audio or change over time - whatever you can imagine.
|
||
|
|
||
|
With custom waves, you can draw the waveform (or the frequency spectrum)
|
||
|
wherever, whenever, and however you want; a great addition since MilkDrop
|
||
|
1.03, where only the built-in waveforms were possible. With custom waves
|
||
|
you can also write per-frame code to control the waves, and per-point code
|
||
|
to place every point (or line segment) on the wave exactly where you want,
|
||
|
and in exactly the color you want, and so on.
|
||
|
|
||
|
Remember those q1-q8 variables that were committed at the end of the preset
|
||
|
initialization code, then reset (to those values) at the beginning of each
|
||
|
frame, and then (potentially) modified in the preset per-frame code? Those
|
||
|
(potentially modified) values of q1-q8 - as they were at the end of the
|
||
|
preset's per-frame code, each frame - are piped into the custom wave & custom
|
||
|
shape per-frame code. So if you read 'q3' in the custom wave per-frame
|
||
|
code, what you're really reading is the value of 'q3' as it was left at the
|
||
|
end of this frame's per-frame code. Again, see the <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A> image
|
||
|
for a diagram of the flow of the values of the q1-q8 varibles.
|
||
|
|
||
|
For custom waves, you can modify q1-q8 and that value will get passed on
|
||
|
to the per-point code. If you then modify q1-q8 in the per-point code,
|
||
|
the modified values will pass on to the next point, much like the per-pixel
|
||
|
code for the preset.
|
||
|
|
||
|
There are, however, 8 additional variables available for custom waves
|
||
|
and shapes: <B>t1-t8</B>. These are very similar to q1-q8, but they exist only
|
||
|
for custom waves & shapes. Recall that q1-q8 exist so that you can carry
|
||
|
custom data (values) from the preset init code and per-frame code, to the
|
||
|
preset's per-pixel code (which uses a different pool of variables).
|
||
|
Likewise, t1-t8 exist so that you can pass custom values from the custom
|
||
|
wave/shape init code, on to the custom wave/shape per-frame code, and
|
||
|
then (in the case of custom waves) on to the per-point code. q1-q8 are
|
||
|
also used to bridge another gap: to carry values from the preset init/per-
|
||
|
frame code, to the custom wave/shape code. Again, see the diagram; it's
|
||
|
probably easier to understand than all of this explanation.
|
||
|
|
||
|
|
||
|
CUSTOM SHAPE PER-FRAME VARIABLES
|
||
|
----------------------
|
||
|
NAME WRITABLE? RANGE DESCRIPTION
|
||
|
---- --------- ----- -----------
|
||
|
sides yes 3-100 the default number of sides that make up the polygonal shape
|
||
|
thick yes 0/1 if ON, the border will be overdrawn 4X to make it thicker, bolder, and more visible
|
||
|
additive yes 0/1 if ON, the shape will add color to sature the image toward white; otherwise, it will replace what's there.
|
||
|
x yes 0..1 default x position of the shape (0..1; 0=left side, 1=right side)
|
||
|
y yes 0..1 default y position of the shape (0..1; 0=bottom, 1=top of screen)
|
||
|
rad yes 0+ default radius of the shape (0+)
|
||
|
ang yes 0..6.28 default rotation angle of the shape (0...2*pi)
|
||
|
textured yes 0/1 if ON, the shape will be textured with the image from the previous frame
|
||
|
tex_zoom yes >0 the portion of the previous frame's image to use with the shape
|
||
|
tex_ang yes 0..6.28 the angle at which to rotate the previous frame's image before applying it to the shape
|
||
|
r yes 0..1 default amount of red color toward the center of the shape (0..1)
|
||
|
g yes 0..1 default amount of green color toward the center of the shape (0..1)
|
||
|
b yes 0..1 default amount of blue color toward the center of the shape (0..1)
|
||
|
a yes 0..1 default opacity of the center of the shape; 0=transparent, 1=opaque
|
||
|
r2 yes 0..1 default amount of red color toward the outer edge of the shape (0..1)
|
||
|
g2 yes 0..1 default amount of green color toward the outer edge of the shape (0..1)
|
||
|
b2 yes 0..1 default amount of blue color toward the outer edge of the shape (0..1)
|
||
|
a2 yes 0..1 default opacity of the outer edge of the shape; 0=transparent, 1=opaque
|
||
|
border_r yes 0..1 default amount of red color in the shape's border (0..1)
|
||
|
border_g yes 0..1 default amount of green color in the shape's border (0..1)
|
||
|
border_b yes 0..1 default amount of blue color in the shape's border (0..1)
|
||
|
border_a yes 0..1 default opacity of the shape's border; 0=transparent, 1=opaque
|
||
|
|
||
|
time NO >0 retrieves the current time, in seconds, since MilkDrop started running
|
||
|
fps NO >0 retrieves the current framerate, in frames per second.
|
||
|
frame NO retrieves the number of frames of animation elapsed since the program started
|
||
|
progress NO 0..1 progress through the current preset; if preset was just loaded, this is closer to 0; if preset is about to end, this is closer to 1.
|
||
|
-note that if Scroll Lock is on, 'progress' will freeze!
|
||
|
|
||
|
bass NO >0 retrieves the current amount of bass. 1 is normal; below ~0.7 is quiet; above ~1.3 is loud bass
|
||
|
mid NO >0 -same, but for mids (middle frequencies)
|
||
|
treb NO >0 -same, but for treble (high) frequencies
|
||
|
bass_att NO >0 retrieves an attenuated reading on the bass, meaning that it is damped in time and doesn't change so rapidly.
|
||
|
mid_att NO >0 -same, but for mids (middle frequencies)
|
||
|
treb_att NO >0 -same, but for treble (high) frequencies
|
||
|
|
||
|
q1 yes any }
|
||
|
q2 yes any }
|
||
|
q3 yes any } Used to carry information
|
||
|
q4 yes any } from the preset per-frame code
|
||
|
q5 yes any } to the custom shape/wave per-frame code.
|
||
|
q6 yes any } see <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A>
|
||
|
q7 yes any }
|
||
|
q8 yes any }
|
||
|
|
||
|
t1 yes any }
|
||
|
t2 yes any }
|
||
|
t3 yes any } Used to carry information
|
||
|
t4 yes any } from the custom shape init code
|
||
|
t5 yes any } to the custom shape per-frame code.
|
||
|
t6 yes any } see <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A>
|
||
|
t7 yes any }
|
||
|
t8 yes any }
|
||
|
|
||
|
|
||
|
CUSTOM WAVE PER-FRAME VARIABLES
|
||
|
---------------------
|
||
|
NAME WRITABLE? RANGE DESCRIPTION
|
||
|
---- --------- ----- -----------
|
||
|
r yes 0..1 base amount of red color in the wave (0..1)
|
||
|
g yes 0..1 base amount of green color in the wave (0..1)
|
||
|
b yes 0..1 base amount of blue color in the wave (0..1)
|
||
|
a yes 0..1 base opacity of the waveform; 0=transparent, 1=opaque
|
||
|
|
||
|
time NO >0 retrieves the current time, in seconds, since MilkDrop started running
|
||
|
fps NO >0 retrieves the current framerate, in frames per second.
|
||
|
frame NO retrieves the number of frames of animation elapsed since the program started
|
||
|
progress NO 0..1 progress through the current preset; if preset was just loaded, this is closer to 0; if preset is about to end, this is closer to 1.
|
||
|
-note that if Scroll Lock is on, 'progress' will freeze!
|
||
|
|
||
|
bass NO >0 retrieves the current amount of bass. 1 is normal; below ~0.7 is quiet; above ~1.3 is loud bass
|
||
|
mid NO >0 -same, but for mids (middle frequencies)
|
||
|
treb NO >0 -same, but for treble (high) frequencies
|
||
|
bass_att NO >0 retrieves an attenuated reading on the bass, meaning that it is damped in time and doesn't change so rapidly.
|
||
|
mid_att NO >0 -same, but for mids (middle frequencies)
|
||
|
treb_att NO >0 -same, but for treble (high) frequencies
|
||
|
|
||
|
q1 yes any }
|
||
|
q2 yes any }
|
||
|
q3 yes any } Used to carry information
|
||
|
q4 yes any } from the preset per-frame code
|
||
|
q5 yes any } to the custom shape/wave per-frame code.
|
||
|
q6 yes any } see <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A>
|
||
|
q7 yes any }
|
||
|
q8 yes any }
|
||
|
|
||
|
t1 yes any }
|
||
|
t2 yes any }
|
||
|
t3 yes any } Used to carry information
|
||
|
t4 yes any } from the custom wave init code,
|
||
|
t5 yes any } to the custom wave per-frame code,
|
||
|
t6 yes any } and on to the custom wave per-point code.
|
||
|
t7 yes any } see <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A>
|
||
|
t8 yes any }
|
||
|
|
||
|
|
||
|
CUSTOM WAVE PER-POINT VARIABLES
|
||
|
---------------------
|
||
|
NAME WRITABLE? RANGE DESCRIPTION
|
||
|
---- --------- ----- -----------
|
||
|
x yes 0..1 the x position of this point that makes up the wave (0=left, 1=right)
|
||
|
y yes 0..1 the y position of this point that makes up the wave (0=bottom, 1=top)
|
||
|
sample no 0..1 how far along we are, through the samples that make up the waveform: 0=first sample, 0.5 = half-way through; 1=last sample.
|
||
|
value1 no any the value of the Left audio channel sample at this point in the waveform (or freq. spectrum).
|
||
|
value2 no any the value of the Right audio channel sample at this point in the waveform (or freq. spectrum).
|
||
|
r yes 0..1 amount of red color in this point of the wave (0..1)
|
||
|
g yes 0..1 amount of green color in this point of the wave (0..1)
|
||
|
b yes 0..1 amount of blue color in this point of the wave (0..1)
|
||
|
a yes 0..1 opacity of this point of the waveform; 0=transparent, 1=opaque
|
||
|
|
||
|
time NO >0 retrieves the current time, in seconds, since MilkDrop started running
|
||
|
fps NO >0 retrieves the current framerate, in frames per second.
|
||
|
frame NO retrieves the number of frames of animation elapsed since the program started
|
||
|
progress NO 0..1 progress through the current preset; if preset was just loaded, this is closer to 0; if preset is about to end, this is closer to 1.
|
||
|
-note that if Scroll Lock is on, 'progress' will freeze!
|
||
|
|
||
|
bass NO >0 retrieves the current amount of bass. 1 is normal; below ~0.7 is quiet; above ~1.3 is loud bass
|
||
|
mid NO >0 -same, but for mids (middle frequencies)
|
||
|
treb NO >0 -same, but for treble (high) frequencies
|
||
|
bass_att NO >0 retrieves an attenuated reading on the bass, meaning that it is damped in time and doesn't change so rapidly.
|
||
|
mid_att NO >0 -same, but for mids (middle frequencies)
|
||
|
treb_att NO >0 -same, but for treble (high) frequencies
|
||
|
|
||
|
q1 yes any }
|
||
|
q2 yes any }
|
||
|
q3 yes any } Used to carry information
|
||
|
q4 yes any } from the preset per-frame code
|
||
|
q5 yes any } to the custom wave per-frame code
|
||
|
q6 yes any } and on to the custom wave per-point code.
|
||
|
q7 yes any } see <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A>
|
||
|
q8 yes any }
|
||
|
|
||
|
t1 yes any }
|
||
|
t2 yes any }
|
||
|
t3 yes any } Used to carry information
|
||
|
t4 yes any } from the custom wave init code,
|
||
|
t5 yes any } to the custom wave per-frame code,
|
||
|
t6 yes any } and on to the custom wave per-point code.
|
||
|
t7 yes any } see <A HREF="q_and_t_vars.gif">q_and_t_vars.gif</A>
|
||
|
t8 yes any }
|
||
|
|
||
|
|
||
|
|
||
|
<A NAME="3e">
|
||
|
<B>e. QUALITY ASSURANCE</B>
|
||
|
----------------------
|
||
|
In order to make sure the presets you create work well on other systems,
|
||
|
keep the following in mind:
|
||
|
|
||
|
1. Design your presets using the default mesh size (32x24) option
|
||
|
from the config panel, or at least check, before you distribute them,
|
||
|
to make sure they look correct at the default mesh size. If your
|
||
|
mesh is too coarse (small), then a viewer with the default mesh size
|
||
|
might see unexpected "bonus" effects that you might not have intended,
|
||
|
and might mess up your preset. If your mesh is too fine, then a
|
||
|
viewer with the default might not see all the detail you intended,
|
||
|
and it might look bad.
|
||
|
|
||
|
2. Keep your presets fast. There's nothing to spoil the mood like
|
||
|
a preset popping up that chokes at 10 fps. Since division is 11
|
||
|
times slower than multiplication (or addition/subtraction), if you
|
||
|
divide a bunch of values by one other value, pre-divide that value
|
||
|
("inv = 1/myval;") and then multiply those other values by that
|
||
|
inverse. Also, never put computations in the per-pixel code that
|
||
|
are the same for every pixel; move these into the per-frame code,
|
||
|
and carry the results to the per-pixel code using the q1-q8 variables.
|
||
|
Remember that maxim: "If a per-pixel equation doesn't use at least
|
||
|
one of the variables { x, y, rad, ang }, then it should be actually
|
||
|
be a per-frame equation."
|
||
|
|
||
|
2. Try to design your presets in a 32-bit video mode, so that its
|
||
|
brightness levels are standard. The thing to really watch out
|
||
|
for is designing your presets in 16-bit color when the "fix pink/
|
||
|
white color saturation artifact" checkbox is checked. This
|
||
|
checkbox keeps the image extra dark to avoid color saturation,
|
||
|
which is only necessary on some cards, in 16-bit color. If this
|
||
|
is the case for you, and you write a preset, then when you run
|
||
|
it on another machine, it might appear insanely bright.
|
||
|
|
||
|
3. Don't underestimate the power of the 'dx' and 'dy' parameters. Some
|
||
|
of the best presets a based on using these. If you strip everything
|
||
|
out of a preset so that there's no motion at all, then you can use the
|
||
|
dx and dy parameters to have precise manual control over the motion.
|
||
|
Basically, all the other effects (zoom, warp, rot, etc.) are just
|
||
|
complicated abstractions; they could all be simulated by using only
|
||
|
{ x, y, rad, ang } and { dx, dy }.
|
||
|
|
||
|
4. If you use the 'progress' variable in a preset, make sure you
|
||
|
try the preset out with several values for 'Time Between Auto
|
||
|
Preset Changes'. The biggest thing to avoid is using something
|
||
|
like sin(progress), since the rate at which 'progress' increases
|
||
|
can vary drastically from system to system, dependong on the user's
|
||
|
setting for 'Time Between Auto Preset Changes'.
|
||
|
|
||
|
|
||
|
|
||
|
<A NAME="3f">
|
||
|
<B>f. DEBUGGING</B>
|
||
|
-----------------------
|
||
|
One feature that preset authors should definitely be aware of is the
|
||
|
variable monitoring feature, which lets you monitor (watch) the value
|
||
|
of any per-frame variable you like. First, hit the 'N' key to show
|
||
|
the monitor value, which will probably display zero. Then all you
|
||
|
have to do is add a line like this to the per-frame equations:
|
||
|
|
||
|
monitor = x;
|
||
|
|
||
|
where 'x' is the variable or expression you want to monitor. Once you
|
||
|
hit CTRL+ENTER to accept the changes, you should see the value of the
|
||
|
per-frame variable or expression in the upper-right corner of the
|
||
|
screen!
|
||
|
|
||
|
Once again, note that it only works for *per-frame* equations, and NOT
|
||
|
for per-pixel equations.
|
||
|
|
||
|
|
||
|
|
||
|
<A NAME="3g">
|
||
|
<B>g. FUNCTION REFERENCE</B>
|
||
|
-----------------------
|
||
|
Following is a list of the functions supported by the expression evaluator.
|
||
|
The list was blatently ripped from the help box of Justin Frankels' AVS
|
||
|
plug-in, since MilkDrop uses the expression evaluator that he wrote.
|
||
|
|
||
|
Format your expressions using a semicolon (;) to delimit between statements.
|
||
|
Use parenthesis ['(' and ')'] to denote precedence if you are unsure.
|
||
|
The following operators are available:
|
||
|
= : assign
|
||
|
+,-,/,* : plus, minus, divide, multiply
|
||
|
| : convert to integer, and do bitwise or
|
||
|
& : convert to integer, and do bitwise and
|
||
|
% : convert to integer, and get remainder
|
||
|
The following functions are available:
|
||
|
int(var) : returns the integer value of 'var' (rounds toward zero)
|
||
|
abs(var) : returns the absolute value of var
|
||
|
sin(var) : returns the sine of the angle var (expressed in radians)
|
||
|
cos(var) : returns the cosine of the angle var
|
||
|
tan(var) : returns the tangent of the angle var
|
||
|
asin(var) : returns the arcsine of var
|
||
|
acos(var) : returns the arccosine of var
|
||
|
atan(var) : returns the arctangent of var
|
||
|
sqr(var) : returns the square of var
|
||
|
sqrt(var) : returns the square root of var
|
||
|
pow(var,var2) : returns var to the power of var2
|
||
|
log(var) : returns the log base e of var
|
||
|
log10(var) : returns the log base 10 of var
|
||
|
sign(var) : returns the sign of var or 0
|
||
|
min(var,var2) : returns the smalest value
|
||
|
max(var,var2) : returns the greatest value
|
||
|
sigmoid(var,var2) : returns sigmoid function value of x=var (var2=constraint)
|
||
|
rand(var) : returns a random integer modulo 'var'; e.g. rand(4) will return 0, 1, 2, or 3.
|
||
|
bor(var,var2) : boolean or, returns 1 if var or var2 is != 0
|
||
|
bnot(var) : boolean not, returns 1 if var == 0 or 0 if var != 0
|
||
|
if(cond,vartrue,varfalse) : if condition is nonzero, returns valtrue, otherwise returns valfalse
|
||
|
equal(var,var2) : returns 1 if var = var2, else 0
|
||
|
above(var,var2) : returns 1 if var > var2, else 0
|
||
|
below(var,var2) : returns 1 if var < var2, else 0
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
<A HREF="#milkdrop_preset_authoring_top">return to top</A>
|
||
|
<A HREF="milkdrop.html">return to milkdrop.html</A>
|
||
|
</PRE>
|
||
|
</HTML>
|