From f5c4671bfbad96bf346bd7e9a21fc4317b4959df Mon Sep 17 00:00:00 2001 From: Indrajith K L Date: Sat, 3 Dec 2022 17:00:20 +0530 Subject: Adds most of the tools --- .../plugins/Milkdrop2/docs/LICENSE.txt | 26 + .../plugins/Milkdrop2/docs/milkdrop.html | 1427 ++++++++++++++ .../Milkdrop2/docs/milkdrop_preset_authoring.html | 1990 ++++++++++++++++++++ .../plugins/Milkdrop2/docs/q_vars.gif | Bin 0 -> 16772 bytes .../plugins/Milkdrop2/docs/t_vars.gif | Bin 0 -> 13585 bytes 5 files changed, 3443 insertions(+) create mode 100644 musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/LICENSE.txt create mode 100644 musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop.html create mode 100644 musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop_preset_authoring.html create mode 100644 musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/q_vars.gif create mode 100644 musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/t_vars.gif (limited to 'musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs') diff --git a/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/LICENSE.txt b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/LICENSE.txt new file mode 100644 index 0000000..06a614e --- /dev/null +++ b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/LICENSE.txt @@ -0,0 +1,26 @@ + LICENSE + ------- +Copyright 2005-2013 Nullsoft, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of Nullsoft nor the names of its contributors may be used to + endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop.html b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop.html new file mode 100644 index 0000000..5d12d5a --- /dev/null +++ b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop.html @@ -0,0 +1,1427 @@ + + +MilkDrop Documentation + + +
+
+MILKDROP 2.1 (February 2009)
+    a Winamp visualization plug-in by Ryan Geiss
+    copyright (c) 2001-2009 Nullsoft, Inc.
+
+
+Useful Links:
+    official milkdrop homepage
+    online forums - for preset sharing, troubleshooting, 
+      comments, and feature requests
+    Nullsoft Winamp
+    Microsoft DirectX
+    milkdrop.co.uk - an excellent third-party preset community site
+
+  
+
+What is MilkDrop?
+-----------------------
+MilkDrop is a music-visualization "plug-in" for the Winamp music player.  
+As you listen to music through Winamp, MilkDrop renders the soundwaves in a 
+visual feedback loop, driven by 3D graphics hardware, to create a 
+rich visual journey through sound.  MilkDrop can also be driven by a live 
+audio feed (microphone or line-in) - see the documentation for details.
+
+MilkDrop 2 is a major upgrade to the original MilkDrop visualizer, opening up 
+the power of modern graphics chips and programmable pixel shaders to the realm 
+of music visualization.  Pixel shaders allow dozens, even hundreds of complex 
+instructions to be executed for every pixel on the screen, every frame.  
+Other new features include jpg textures, gaussian blurring, a preset "mash-up" 
+feature, and a prest "back" button.  MilkDrop 2 is backwards-compatible with 
+presets from MilkDrop 1.
+
+
+
+Section Listing
+-----------------------
+    1. requirements
+    2. installation
+    3. tweaking
+    4. usage
+        4.a. keyboard commands
+        4.b. config panel
+        4.c. preset authoring
+        4.d. rating system
+        4.e. custom messages
+        4.f. sprites
+    5. troubleshooting
+    6. known issues / misc. / tips
+    7. using line-in (for live audio input)
+    8. acknowledgements
+    9. version history
+
+
+
+
+1. Requirements
+-----------------------
+    1. Windows 98, ME, 2000, XP, or later.
+    2. Hardware-based 3D graphics acceleration (i.e. a video card with 3D support)
+        supporting DirectX 9 with at least 8 MB of video memory; 
+        however, we strongly recommend a GeForce 5700 (or better), 
+        or a Radeon 9600 (or better).
+    3. Winamp 5.12 or later ( http://www.winamp.com/ ).
+    4. DirectX 9.0 or later ( http://www.microsoft.com/windows/directx/ ).
+
+
+
+
+2. Installation
+-----------------------
+    MilkDrop 2 comes with Winamp.  To install it, just download and
+    install the latest version of Winamp.  During the installation,
+    make sure the "MilkDrop 2" visualizer option is checked, so that 
+    it gets installed, too.  
+
+    Once Winamp is installed, launch it.  Load some music files into
+    your playlist and start playing some music.  (Be sure to play some music 
+    before trying to launch the visualizer - otherwise you'll just see a 
+    black screen.)  
+    
+    Once music is playing, hit CTRL+K and a list of visualization 
+    plug-ins will appear.  Select "MilkDrop 2" from the list.  Then click 
+    the "Start" button, and it will launch the visualizer.  
+
+    Quick Tips:    
+      * If you want to go full-screen, double-click on the visualizer itself.
+      * CTRL+SHIFT+K starts or stops the visualizer.
+      * To configure MilkDrop's options, exit the visualizer and hit ALT+K.
+    
+    If you have trouble getting MilkDrop to run properly after installation, 
+    try installing various recent WHQL drivers for your video card, or installing 
+    DirectX; doing these two things (especially the first) will fix 99% of
+    problems. See the Troubleshooting section of the documentation for more
+    information. 
+
+
+    
+
+3. Tweaking to achieve the best image quality
+-----------------------
+    a) Fullscreen Display Mode   [first tab of config screen]
+        
+        When you run MilkDrop fullscreen, it changes the display
+        mode to whatever you select here.  Generally speaking,
+        the speed (framerate) and smoothness of MilkDrop will drop
+        as the resolution (number of pixels on the screen)
+        increases.  So, if it's running to slow in fullscreen 
+        mode, try selecting a smaller fullscreen display mode. 
+        
+    b) Canvas Stretch  [second tab]
+    
+        This option lets you trade resolution [crispness] for
+        speed.  If MilkDrop runs too slow, in any mode (windowed/
+        fullscreen/desktop), try cranking up the canvas stretch
+        to, say, 1.5X or 2X.  The image will not look as crisp,
+        but MilkDrop will probably run much faster.  (Assuming
+        that your graphics chip was the bottleneck.)
+
+    c) Mesh Size  [second tab]
+
+        This is the main option that affects how much processor
+        (CPU) MilkDrop uses.  If you crank it up far beyond the
+        default, expect to be CPU-bound (where your framerate drops
+        because the CPU is the bottleneck).  To get MilkDrop to
+        speed up, drop the Mesh Size back down.  The Mesh Size 
+        decides how many points on the screen the per-vertex
+        equations will be executed for; the higher the mesh size,
+        the more fidelity you will see in the motion.  
+        
+    d) tips for LCD and laptop users
+
+        LCD screens: Note that most LCD screens (flatpanels) usually run 
+        at a fixed frequency only - usually 60 Hz - meaning that they update 
+        the screen 60 times per second.  However, sometimes the video driver 
+        reports that it supports other refresh rates, such as 72, 75, 85, etc.  
+        It is strongly recommended that [for fullscreen mode, and for Windows 
+        in general] you choose a display mode with a 60 Hz refresh rate, for 
+        the smoothest possible animation.  For this plugin, you will also want 
+        to choose Maximum Framerates that divide evenly into 60 - such as 60, 
+        30, 20, 15, 12, 10, 6, 5, and so on - so that the # of times the LCD 
+        shows each frame of animation remains constant, resulting in the 
+        smoothest possible animation.
+
+    e) color (bit) depth: 16 or 32?
+    
+        The answer, nowadays, is a resounding "32".  Video memory
+        is plentiful these days; use 32 bit color, for both your 
+        windows desktop (...so that MilkDrop's windowed mode can
+        run at 32 bits) and for MilkDrop's Fullscreen Display Mode
+        setting (where "8888" denotes 32 bits).
+        
+        Some ancient video cards don't have enough memory to run MilkDrop
+        properly (or smoothly) in 32 bits, though; you might want to 
+        try 16-bit color if your card has less than 32 MB of video 
+        memory, if you are using a laptop, or if your video card is 
+        significantly old.  In the MilkDrop config panel, 16-bit modes
+        show up as "555" or "565".
+
+        If you find that your card runs best in 32-bit color, you should
+        have no problems with brightness levels while running MilkDrop.
+        However, if your card runs best in 16-bit color, you should 
+        then adjust the Brightness slider on the second tab of the config 
+        panel (which only affects 16-bit color video modes!).  The goal 
+        is to make the image as bright as possible, without oversaturating 
+        it (washing it out, often to bright pink or white).  This setting 
+        also varies for different cards, depending on how the card rounds 
+        color values, so we recommend seeing how bright you can set the 
+        slider (closer to '0') without oversaturating the image.  Usually,
+        a setting of '0' or '2' works the best.
+
+            
+    
+
+
+4. Usage
+-----------------------
+    
+    4.a. Keyboard Commands
+    
+        The following keys can be used to control MilkDrop while it is running.
+        (Note: pressing F1 while MilkDrop is running will show you this list)
+            
+            GENERAL
+            escape: exit to winamp
+            
+            PRESET LOADING
+            BACKSPACE: return to previous preset
+            SPACE: transition to next preset
+            H: instant Hard cut (to next preset)
+            R: toggle random (vs. sequential) preset traversal
+            L: load a specific preset (invokes the 'Load' menu)
+            +/-: rate current preset (better/worse)
+            scroll lock: lock/unlock current preset 
+                (keyboard light on means preset is locked)
+                (prevents random switch to new preset)
+            A: aggregate preset - loads a random preset,
+                steals the warp shader from a different random preset,
+                and steals the composite shader from a third random preset.
+            D: cycle between various lock-states for the warp and
+                composite shaders.  When one of these shaders is locked,
+                loading a new preset will load everything *except* the
+                locked shaders, creating a mix between the two presets.
+
+            PRESET EDITING AND SAVING
+            M: show/hide the preset-editing menu
+            S: save new preset (asks you for the new filename)
+            N: show per-frame variable moNitor
+                (see milkdrop_preset_authoring.html)
+
+            MUSIC PLAYBACK
+            z/x/c/v/b: navigate playlist (prev/play/pause/stop/next)
+            U: toggle shuffle
+            P: show playlist
+            up/down arrows: volume up/down
+            left/right arrows: rewind/ffwd 5 seconds
+            SHIFT + left/right arrows: rewind/ffwd 30 seconds
+
+            FUNCTION KEYS                                
+            F1: show help screen
+            F2: show song title
+            F3: show song length
+            F4: show preset name
+            F5: show fps (frames per second)
+            F6: show rating of current preset
+            F7: re-read custom message file (milk_msg.ini) from disk
+            F8: jump to new directory (for presets)
+            F9: toggle stereo 3D on/off
+
+            SPRITES AND CUSTOM MESSAGES (FOR VJ's)
+            T: launch song title animation
+            Y: enter custom message mode
+                ##: load message ## (where ## is a 2-digit numeric code (00-99) 
+                    of a message defined in milk_msg.ini)
+                *: clear any digits entered.
+                DELETE: clear message (if visible)
+                F7: re-read milk_msg.ini from disk
+            K: enter sprite mode
+                ##: load sprite ## (where ## is a 2-digit numeric code (00-99) 
+                    of a sprite defined in milk_img.ini)
+                *: clear any digits entered.
+                DELETE: clear newest sprite 
+                SHIFT + DELETE: clear oldest sprite
+                CTRL+SHIFT+DELETE: clear all sprites
+                F7: no effect (milk_img.ini is never cached)
+            SHIFT + K: enter sprite kill mode
+                ##: clear all sprites with code ##
+                *: clear any digits entered.
+            CTRL + T/Y: kill song title and/or any custom messages
+            CTRL + K: kill all sprites
+            
+            Note that there are more keys available, but because many
+            are only relevant to people designing their own presets, 
+            they are listed in the preset authoring guide instead.
+            
+            
+    
+    4.b. config panel
+    
+        The configuration panel lets you customize the way MilkDrop runs.
+        To learn how to get to the configuration panel, see the "Installation"
+        section above.
+        
+        Once you're in the config panel, you'll see a number of tabs
+        at the top, some dropdown boxes, and some checkboxes.  Each
+        of the tabs at the top brings you to a different page of 
+        configuration options.  To get help on a setting, simply click
+        on the '?' in the upper-right corner of the config panel, 
+        and then click on the setting you want help with.
+
+            
+
+    
+    4.c. preset authoring
+    
+        Please see the included text file, milkdrop_preset_authoring.html,
+        for instructions on how to create and save your own presets.
+
+
+    
+    4.d. rating system
+
+        The built-in rating system allows you to rate each preset on a scale 
+        from 0 to 5.  A rating of 5 is very good, while a rating of 0 is
+        the worst.  The ratings decide how often the presets will be randomly
+        loaded.  If a preset has a rating of 0, it will never be randomly
+        loaded (unless they're all zero; then they all have an equal chance).
+        
+        To show the rating for a preset, press F6.  You can adjust the 
+        rating for a preset with the +/- keys.  When you make adjustments,
+        they save automatically; there's no need to save the preset to make
+        the rating change permanent.
+        
+        Here's a recommended interpretation of the numeric values:
+            0 = I never want to see this preset again
+            1 = very ugly
+            2 = mediocre
+            3 = fair
+            4 = good
+            5 = downright stimulating
+            
+        If a preset seems "lost" because you set its rating to 0 and it
+        won't ever come back, you can always load it up by hitting 'L'
+        to conjure the 'Load Preset' menu, finding the preset you want,
+        loading it, then hitting +.
+            
+    
+    
+    
+    4.e. custom messages
+
+        ABOUT CUSTOM MESSAGES
+            The "Custom Message" feature of MilkDrop allows you to display
+            short text messages on the screen while MilkDrop is running.
+            They are highly configurable; you can set all of the following
+            parameters: the font, the size, the positioning, color, bold 
+            state, italic state, and so on; and you can even have it 
+            randomize some of these properties.
+
+        CREATING THE MESSAGES
+            You can save up to 100 messages in the file MILK_MSG.INI in
+            your Winamp\Plugins\ folder.  To open this file, go to the 
+            MilkDrop configuration screen (ALT+K from Winamp) and click the
+            "Edit Custom Messages" button.  Or, you can just edit it 
+            manually if you know how; it's plain-text.
+            
+            The first thing you see when you open the file is a bunch of
+            lines that start with two forward slashes (//).  These are
+            comment lines, and they explain the syntax for adding a font
+            or a message to the file.  This is your main reference for
+            finding out what all the parameters do for the fonts & messages;
+            it is recommended that you leave this information in the file,
+            although it can be removed or (modified) and the messages will
+            still work.
+
+            After the comments come first the fonts, then the messages.
+            The fonts are simply a way to specify a typeface, bold state,
+            italics state, and red/green/blue color for the font.  You can 
+            configure up to 16 fonts like this (numbered 00-15). These fonts
+            will serve as template fonts for the custom messages.
+
+            The next section is the actual messages.  Each one has a
+            text message (the 'text' parameter) that will be shown to the
+            user, and each one references one of the 16 fonts that were
+            defined in the previous section.  You can also specify the
+            size (size), position (x,y), a growth factor (growth) that
+            will grow/shrink the message over its lifetime, the number
+            of seconds to show the message (time), and the fraction of that
+            time that is spent fading in (fade).  
+
+            You can also randomize some of these values: 'randx' and 'randy'
+            will randomly perturb the (x,y) coordinates every time the message
+            is shown to the user, and 'randr'/'randg'/'randb' will randomly
+            perturb the (r,g,b) color in the same way.
+
+            Finally, you can override any of the default properties for the
+            font that this message uses: (face, bold, ital, r, g, b).
+
+        INVOCATION AND USAGE
+            There are two ways to invoke custom messages: one automatic,
+            the other manual.  
+
+            The automatic way is to go to the MilkDrop config panel (ALT+K),
+            click the 'More Options' button, and set the value in the
+            'Time between RANDOM custom messages' box to something greater
+            than zero.  This will cause MilkDrop to randomly display custom 
+            messages while it is running, and the average time (in seconds) 
+            between messages will be the value you entered here.  If you 
+            wish to disable random custom messages, set this value to -1
+            (or any negative number).  Note that all messages in the file
+            have an equal change of being picked.
+
+            The manual way is to type in the two-digit code (00-99) of the 
+            message while MilkDrop is running.  However, you can't use the 
+            numeric keypad for this - you have to use the numbers at the 
+            TOP of your keyboard to do it.  If you mess up while entering
+            the first digit, just press the '*' key to start over.
+            
+            Note that if you change the MILK_MSG.INI file while MilkDrop
+            is running, you will not be able to see the changes until
+            you hit F7, which tells MilkDrop to re-read the MILK_MSG.INI 
+            file from disk.
+
+
+    
+    4.f. sprites
+
+        ABOUT SPRITES
+            The "Sprite" feature of MilkDrop allows you to display
+            any image of your choice in the foreground (on top of 
+            MilkDrop) while it runs.  The sprites can fade in and out,
+            move around, respond to the music, and so on.  You define
+            them in a file - milk_img.ini in your winamp\plugins
+            directory - much like you define custom messages, each 
+            having an identifying code number from 00 through 99 (used
+            to invoke them).  However, the way the individual sprites
+            are defined is different; you write code for them, instead
+            of just setting parameter values.  This is a little bit 
+            tougher to do (it's very much like preset authoring), but
+            adds a great deal of flexibility to what you can do with
+            the sprites.
+
+        CREATING THE SPRITES
+            You can define up to 100 sprites in the file MILK_IMG.INI in
+            your Winamp\Plugins\ folder.  To open this file, go to the 
+            MilkDrop configuration screen (ALT+K from Winamp) and click the
+            "Edit Sprites" button.  Or, you can just edit it manually if 
+            you know how; it's plain-text.
+            
+            The first thing you see when you open the file is a bunch of
+            lines that start with two forward slashes (//).  These are
+            comment lines, and they explain the syntax for creating a sprite. 
+            This is your main reference for finding out what all the 
+            parameters do for the fonts & messages; it is recommended that 
+            you leave this information in the file, although it can be removed 
+            (or modified) and the sprites will still work.
+
+            After the comments come the sprite definitions.  Each sprite is
+            made up of one parameter that indicates the image file to use
+            (this is the 'img=...' line), and two types of code: initialization
+            code, and regular code.  
+            
+            The first - initialization code - is executed only once, when you 
+            launch the sprite.  Use it to do one-time initialization of variables
+            (such as the opacity (a), rotation angle (rot), position (x,y),
+            and so on) or to invent new variables that you will access later.
+            This code is marked by the 'init_1=...', 'init_2=...', etc. lines.
+            
+            The second type of code - marked by 'code_1=...', 'code_2=...', etc.
+            - is executed every frame, just prior to plastering the sprite on 
+            the screen.  Use it to animate the sprite, moving it around (changing
+            x,y), scaling it up and down (sx,sy), fading it in and out (a),
+            changing its color, and so on.
+            
+            Please see the comments included in the sample milk_img.ini file
+            for full details and examples on how to author sprites.
+
+        INVOCATION AND USAGE
+            There is currently only one way to invoke sprites: manually.
+            To do this, first press 'K' to enter 'sprite mode' (while 
+            running MilkDrop).  Now, whenever you type in a two-digit 
+            code (00-99), MilkDrop will try to find & launch the sprite
+            you've requested, from the milk_img.ini file.  If there is
+            an error, it will display an error message in the upper-right
+            corner.  Note that to enter the two-digit code, you can't use 
+            the numeric keypad; you have to use the numbers at the TOP of 
+            your keyboard.  
+
+            If you make an error entering the first digit of the code, 
+            just press '*' to start over.  If you want to
+            clear the most recently-invoked sprite, press DELETE.  If you
+            want to clear the oldest sprite, press SHIFT + DELETE.  If you
+            want to clear all sprites, press SHIFT + CTRL + DELETE.
+            
+            If you want to clear sprites by their 2-digit code, press
+            SHIFT + K (instead of just 'K') to enter 'sprite kill mode.'
+            Now, when you enter a two-digit code, instead of invoking
+            the sprite, MilkDrop clears all running sprites with that
+            two-digit code.
+
+    
+
+
+5. TROUBLESHOOTING
+-----------------------
+    
+    If MilkDrop has a critical problem (e.g. fails to load, freezes, etc.)
+    or if the image is distorted, torn, corrupted, or all one solid color,
+    try the following two suggestions to resolve the problem.  In 90% 
+    of these cases it can be fixed.  If you have a different problem, 
+    scroll down past this part and try to find the appropriate symptom 
+    and its solution.
+
+    1. UPDATE YOUR VIDEO DRIVER, OR TRY OTHER DRIVERS
+    
+        Almost all display problems are caused by buggy video drivers!
+        
+        A "driver" is a piece of software that translates graphics-related 
+        commands from programs, like MilkDrop, into the native language of 
+        your specific graphics hardware.
+
+        For desktop machines, there are typically three sources for video drivers: 
+            1) those from the *chip* manufacturer's website (usually 
+                nvidia.com or ati.com) (best source) 
+            2) those from the card manufacturer's website (LeadTEK, PNY, etc.)
+            3) those that shipped with Windows (yuck)
+        
+        For laptops:
+            1) the driver from the *laptop* manufacturer
+            2) (maybe) the driver from the graphics chip manufacturer 
+                (ATI, Nvidia, etc) - however, it's fairly common to find 
+                that the laptop requires a custom driver written by the
+                laptop manufacturer.
+            3) the driver that shipped with Windows (yuck)
+
+        Give them all a shot.  Track down every driver you can find for
+        your card, and try it.  Try the WHQL ones first - these versions of
+        the drivers have passed "Windows Hardware Quality Labs" certification
+        and are usually the more stable and reliable ones.  
+        
+        In general, it's a very good idea to use only Microsoft-certified 
+        WHQL drivers for your video card.  Often people want to get the newest, 
+        fastest beta drivers, but these drivers are almost ALWAYS riddled 
+        with new bugs.  You can also watch the version number of the drivers
+        a company releases - if the version number just jumped to a new
+        series (such as from the 70's to the 80's), watch out, it probably 
+        has a lot of bugs that need worked out - give it 3-4 months before
+        expecting the new driver series to work well.  With video drivers,
+        the newest isn't always the best!
+
+        Here is a list of some common card/chip manufacturers and where 
+        to get their drivers.  Don't forget to choose the WHQL driver!
+        
+            [ NVIDIA driver ]
+                Card manufacturers using NVIDIA (GeForce) graphics chips:
+                (note - most of these just link you to the nvidia driver above)
+                [ XFX ]
+                [ EVGA ]
+                [ BFG ]
+                [ PNY ]  
+            [ ATI driver ] 
+                Card manufacturers using ATI (Radeon) graphics chips:
+                [ VisionTek ]              
+                [ Diamond ]                
+            [ Intel ] - then click 'graphics' on the left
+            [ SiS ] - agree, then select 'graphics drivers'
+            [ S3 ] - then click 'drivers'
+            [ VIA ]    
+            [ Matrox ]
+            [ Creative Labs ]
+            
+            For others - or in general - if your graphics chip is made by Trident, 
+            for example, then try a google search for:
+            
+                Trident graphics driver
+                        
+            Then click on "support", then "drivers" (or "downloads"), then
+            "graphics driver", and so on.
+                        
+
+    2. [RE]INSTALL DIRECTX
+    
+        Make sure you have a quasi-recent version of Microsoft DirectX
+        installed.  In reality, though, almost every PC in the world has
+        DirectX 9 on it at this point, so this shouldn't be a problem.
+        If you go to download it, you'll only be able to find DirectX 10 -
+        this is fine to install, though, as it includes DirectX 9 inside 
+        it.  As a last resort, though, if you are having problems,
+        you could try re-installing DirectX to see if it helps.
+    
+    
+    If you're having a non-critical problem, browse the following list of
+    common problems and their causes and solutions.  Note that for each symptom-
+    cause-solution block, there can be multiple symptoms with the same cause and 
+    solution, and the same symptom might be listed in multiple blocks.
+  
+    If the solutions below don't work for you, please visit the forums at
+    http://www.nullsoft.com/free/milkdrop, where you can read the most
+    recent troubleshooting issues and solutions.
+        
+
+    ENTRY 1
+    SYMPTOM:
+        -any error message saying "Failed to create ..." 
+            or "not enough memory...", or
+        -only a portion of the screen displays correctly; the rest is 
+            either filled with garbage or badly flickering
+    CAUSE:
+        1) Your video card might not have enough memory to run MilkDrop at 
+        the resolution (screen width and height) you've picked, 
+        2) your drivers might be out of date, 
+        3) you might need to reinstall DirectX (very very rare), or
+        4) your graphics card might be to crappy to *actually* run
+             pixel shaders well.
+    SOLUTION:    
+        1) To battle video memory problems:
+
+            Go to the config panel and try smaller video modes (e.g.,
+            320x240 is smaller than 640x480).  Even better is to try
+            a lower color bit depth; if you'd selected a 32-bit ("8888") 
+            video mode before, try a 16- ("565" or "555") or 24-bit ("888") 
+            one, for example.  Note that it might only work in one of them; 
+            so make sure you try them all.  Trying these things is especially 
+            important on laptops with limited video memory, or older video 
+            cards with a small amount of video memory.
+        
+            Finally, you can try locking the texture size (or "canvas size") 
+            to 256x256 pixels, just to see if that fixes the problem.  
+            If it does, try using a smaller fullscreen video mode to
+            free up some memory, or if running windowed, close other
+            graphics-hungry applications.
+        
+        2,3) for instructions on how to reinstall DirectX or update 
+            drivers, go here.
+            
+        4) Go to the MilkDrop config panel (hit ALT+K) and on the second tab, 
+            in the "Pixel Shaders" box, select "None."  Now does MilkDrop run 
+            ok?  If so, your video card probably just can't reliably run
+            pixel shaders, due to either inferior hardware, or it could
+            be the driver.  You can always try setting "Pixel Shaders" 
+            back to "Auto" and then installing a newer (preferably WHQL) 
+            video driver.
+
+
+    ENTRY 2
+    SYMPTOM:
+        -When I go to the Load Preset menu ('L') in MilkDrop, some of the
+            presets on disk are missing.
+        -I downloaded some new presets and put them in my Plugins\MilkDrop2\Presets
+            directory, but I can't access them from within MilkDrop.
+    CAUSE:
+        You probably have an older video card that can't handle the pixel
+        shaders needed to run some of the presets.  MilkDrop automatically
+        hides any presets from you that you can't run.
+    SOLUTION:
+        * You could buy a new graphics card - one that meets the minimum
+        recommendation for MilkDrop 2.  These cost less than $40.
+        * You could try forcing MilkDrop to try to run these presets.
+        Sometimes MilkDrop just hides them from you because it predicts
+        they will run horribly slow on your graphics card; in case it
+        is wrong about that, try this.  Go into the MilkDrop config
+        panel (ALT+K) and go to the More Settings tab.  Under the 
+        "Pixel Shaders" option, change it from "Auto" to "Shader Model 2"
+        or "Shader Model 3".  Then try to run MilkDrop and see if the
+        presets appear.  If they do, you're in luck; if they don't, your
+        GPU really doesn't support those shader models.
+    
+
+    ENTRY 3
+    SYMPTOM:
+        MilkDrop always looks the same - it's always showing the same
+        preset, and it never changes to a new preset unless I tell it to.
+    CAUSE:
+        Scroll Lock is on.
+    SOLUTION:
+        The Scroll Lock key is how you tell MilkDrop to lock the current
+        preset - i.e. don't randomly transition to a new preset unless you 
+        do it.  The state of the Scroll Lock key is remembered when you
+        start or stop MilkDrop, too, so be careful of that.  If you are
+        experiencing this problem, you can fix it in any of the following
+        three ways:
+          1. hit Scroll Lock while MilkDrop is running (and the viz window is active);
+          2. load up the MilkDrop config panel (ALT+K), go to the More Settings
+              tab, and uncheck the "Start milkdrop with preset lock (scroll lock) 
+              key ON" box;
+          3. if you're using a modern skin, there is a "random" button on
+              the frame of the window, which is the inverse of the Scroll Lock
+              state - i.e. you probably have Scroll Lock on and "random" off.
+              Click the "Random" button to turn random transitions back on
+              (and notice that scroll lock gets turned off as a result).
+       
+    ENTRY 4
+    SYMPTOM:
+        I was browsing for presets from within MilkDrop ('L') key and 
+        got lost.  How do I get back to my presets?
+    SOLUTION:   
+        Two ways to fix this.  The easiest is to just reset MilkDrop
+        to its defaults - hit ALT+K to load the MilkDrop config panel,
+        then click the 'Defaults' button.  The next time you launch
+        MilkDrop, it will start you in the default preset directory.
+        
+        To fix it manually (and preserve all your settings), run
+        MilkDrop, hit F8, and paste in this path:
+          C:\Program Files\Winamp\Plugins\Milkdrop2\presets
+        [or equivalent].
+        
+        Another way to fix it is to hit 'L', and browse all the way 
+        down to the root folder (repeatedly select ".."), then
+        go into Program Files, Winamp, Plugins, MilkDrop2, and finally,
+        presets.
+        
+            
+    ENTRY 5
+    SYMPTOM:
+        -things flicker through (such as my AIM window ticker, taskbar
+        clock, web page animations, etc.) when I'm running MilkDrop
+        in fullscreen mode.
+    CAUSE:
+        You're probably running MilkDrop fullscreen at the same
+        resolution & color depth as your desktop, and Windows isn't 
+        properly handling MilkDrop's request for exclusive access to the
+        screen, and is still letting other applications paint (draw)
+        themselves.
+    SOLUTION:
+        Change either your Windows desktop resolution or color depth, or 
+        MilkDrop's fullscreen resolution or color depth, so that there
+        is some difference between the two.   (To change your Windows 
+        display settings, go to the Start Menu -> Settings -> Control 
+        Panel -> Display -> Settings tab, and then change the "colors" 
+        or "screen area" settings from there.)  Also make sure you're
+        not using "fake" fullscreen mode (...uncheck this box on the
+        main screen of the config panel).
+
+
+
+
+6. Known Issues / Misc. / Tips:
+---------------
+    a. Tip for video capture: if you'd like to save sequences of video 
+        from this plugin, there are several programs out there that will 
+        let you do this.  Warning: you will need a ton of free hard drive 
+        space, and a fast CPU helps.  A few of these programs are:
+            "FRAPS"               http://www.fraps.com/
+            "Hypercam"            http://www.hyperionics.com
+    
+    b. Close other apps:
+        For the best graphics performance, try to close as many other 
+        applications as you can, before running the plugin, especially 
+        those that tend to work in the background, such as anti-virus 
+        or file-swapping software.  Also, if you must leave other 
+        applications open, try to minimize them (i.e. shrink the window 
+        down to the taskbar) so that they stay out of the painting loop.
+    
+    c. Windows Vista / Winamp with per-user settings
+        Be aware that if you're running Vista as a non-admin user,
+        you can't write to (or delete from) files in the Program Files
+        directory, which is were MilkDrop 2 is installed.  So, anything
+        you try to write or save (like milkdrop's settings file, milk2.ini; 
+        or presets) will probably end up deep in some user-specific, 
+        virtualized "Program Files" directory somewhere on your hard 
+        drive.  Yell at Microsoft for this one!
+        
+        Also, if you installed Winamp with per-user settings (instead of 
+        shared settings) - on any OS, not just Vista - be aware that your
+        .INI files (milk2.ini, milk2_img.ini, milk2_cfg.ini) are all
+        stored in a folder like this:
+            
+            C:\Documents and Settings\\Application Data\Winamp\Plugins         
+            
+        (Note that 'Application Data' is a hidden folder.)  However,
+        presets, textures, and things like that are all shared between
+        users, in the real [c:\Program Files]\winamp\plugins\milkdrop2 folder. 
+        If you want to keep your presets separate, you can still do that, 
+        though - just put them in a personal folder, and then seek to it
+        from within MilkDrop.  If you're using per-user settings in Winamp,
+        it will remember which folder you last used.
+        
+
+
+7. Using Line-In
+-----------------------
+    If you want to use your sound card's Line-In or CD Audio inputs for
+    sound data (instead of mp3 files), you can do this.  Do the following:
+        1. CONNECT WIRES
+            Connect your audio source (a stereo, a live feed, whatever) into
+            the line-in (or microphone) 1/8" jack on your sound card.  You
+            might want to test & verify that your cable is good before doing 
+            this.
+        2. SELECT SOUND INPUT CHANNEL & ADJUST VOLUME
+            In Windows, double-click the speaker icon in your systray (where
+            the clock is).  Then, on the menu, go to Options -> Properties
+            and select the "Recording" option.  Then make sure the Line In
+            (or Microphone) input channel (whichever is appropriate for
+            your case) is SELECTED (with a check mark) and that the volume 
+            is close to, or at, the maximum.  Hit OK.           
+        3. TELL WINAMP TO USE LINE-IN
+            Open Winamp, and hit CTRL+L (the "Open Location" hotkey).  Now
+            type in "linein://" as the location you want to open.  (Leave out
+            the quotes and make sure you use FORWARD slashes.)  Hit PLAY
+            ('x' key for the lazy), and the little built-in oscilloscope (or 
+            spectrum analyzer) in Winamp should start showing your signal.
+        4. RUN MILKDROP
+            Run MilkDrop as usual.  If the waves are too small or large, 
+            either adjust the volume from Windows' Volume Control, or adjust
+            the sound level at the source.       
+   
+    If you are doing shows using live audio, and if you have a multiple monitor
+    setup, you might also want to use the "VJ mode" feature, which lets you 
+    control MilkDrop (even editing shaders on the fly, etc.) via a separate monitor.
+
+
+
+
+8. Acknowledgements
+-----------------------
+    A very special thanks & triple word scores out to Francis Gastellu
+    and Justin Frankel for the use of their quite-excellent 
+    realtime mathematical expression evaluation library, evallib. 
+
+    A huge thanks to Rovastar for running milkdrop.co.uk and all
+    of the work and passion he has put into making MilkDrop great.
+
+    Also, a super special thanks go out to the following preset 
+    authors for their excellent artistic & mathematical work:
+
+        Aderrasi
+        Bill Melgren
+        Che
+        CTho
+        Idiot
+        Illusion
+        Krash
+        Mstress
+        Rovastar
+        Rozzor
+        Studiomusic
+        Telek
+        Tobias Wolf Boi
+        Unchained
+        Zylot
+
+        ...and to everyone else who has contributed.
+
+
+
+
+
+9. Version History
+-----------------------
+2.2 - November 2009
+    - updated to use ns-eel2 (thanks Justin)
+
+2.1 - January 2009
+    -pixel shader 2.0 & 3.0 support tweaks
+    -unicode support for F2 key feature
+    -removed some older Milkdrop presets and added some newer ones to Winamp installer
+
+2.0e - August 2008
+    -added localization support    
+    -unicode support for milkdrop playlist and title    
+    -tweaked menus
+
+2.0d - January 2008
+    -worked around colossal Intel driver bugs.  See (or skip) long description in next item.    
+    -tightened up various uses of the DX9 api, to decrease the chances of bugs due to poor DX9 compliance
+        by drivers for lower-end graphics chips (namely Intel integrated graphics).  Most importantly,
+        all Intel drivers seem to implement DrawIndexedPrimitiveUP() incorrectly, which was killing
+        MilkDrop.  Since Intel has has this collosal failure in their driver for eons, I decided to work
+        around it, and removed all calls to this function.  MilkDrop should now run properly on Intel
+        graphics chips.
+    -also did the following little things to help decrease chances of buggy driver interactions:
+        -now using more exact D3DFVF_TEXCOORDSIZE2(0,1,2) specifiers, in addition to _TEX2, etc.
+        -cleaned up headers (vertex declarations) in data\*.fx files to more closely match the vertex buffers.
+        -set z==0 for all vertices during the composite shader
+    -fixed some bugs w/giant mesh sizes
+
+2.0c - December 2007 (bundled with winamp 5.51)
+    -if a texture (used in a shader) is not found, MilkDrop now also looks in the current preset folder
+        to try and find it.  This makes it so that preset downloaders can be lazy and just put 
+        the presets, along with the textures that come with them, into the same directory.
+    -fixed a bug where blur textures weren't always being sampled with bilinear filtering
+    -fixed a bug where it would sometimes crash when exiting fullscreen mode while using a modern skin
+        (needed to tell Winamp that we were the viz window, via SET_EMBED_GUID(avs_guid))
+    -desktop mode no longer causes explorer to crash in Windows Vista; it instead just shuts 
+        off the icon-re-creation code.
+    -desktop mode: fixed default placement of icons, when taskbar is on the left/top side of the screen.
+    -removed Winamp version check, so people can run it with older winamps (within reason)
+        -if warand() function can't be found (older winamps), it calls a wrapper fn to rand()
+    -fixed font face for custom messages - was errantly using song title font face for custom msgs
+    -song title texture size is now based on max of screen width vs. height, rather than just width.
+    -simple waveform no longer draws itself when its alpha is less than 1/256 (0.004).
+    -added some cool new presets / filtered out some old crummy ones & repeats
+    -changes of note for preset authors:
+        -added "pixelsx" and "pixelsy" to preset's main per-frame and per-vertex equations. 
+            (equiv. of "texsize.xy" in shaders)
+        -custom waves: you can now vary the # of samples from the custom wave per-frame code.
+            Added new var, "samples", to custom wave init code [read only] and per-frame code [r/w] - 
+            tells you (and lets you set) the # of samples to draw for the wave.
+        -'time' value in shaders now wraps back to 0, after 10,000 seconds spent on a preset 
+            (to avoid precision jitters)
+        -fixed bug where 'Draw Thick' was never working for custom waves.
+        -added "#define tex3d tex3D" to include.fx
+    ---( changes after this point were made in v2.0a, 25 Oct 2007, which wasn't officially released... )--- 
+    -Preset list scan (when milkdrop launches) now happens in a background thread, 
+        so there is no drop in framerate while the scan is done.
+    -added instancing to custom shapes!!
+        -you can now set the # of instances for each of the 4 custom shapes
+           [1..1024]
+        -the per-frame code will actually be called 'num_inst' times,
+           and each time, the variable 'instance' will increment (0,1,2,... num_inst-1).
+    -lots of new presets
+    -plugin no longer has a taskbar icon when running in desktop mode
+    -shader writing: tex2d() now works (before only tex2D() worked)
+    -fixed default fullscreen display mode (...if you'd never gone to the config
+        panel and saved your settings, it defaulted you to 1024x768; now it
+        defaults you to your desktop res).
+    -fixed a few blending bugs (and greatly cleaned up the code) 
+        for transitioning between presets with mixed pixel shader versions
+    -transitions: when booleans from the old comp shader interpolate 
+        during a blend, if the old & new shaders did & didn't use a comp shader 
+        (or vice versa), then it will now be smart about when it switches the 
+        boolean, so you don't see any avoidable jumps.  (mostly for darken, 
+        video echo orientation, brighten, solarize, etc.)
+    -presets now save with a few less decimal places for most of the values (less waste)
+    -finally fixed seldom-seen wave bug; it was due to per-frame code "wave_mystery = time*0.03;" when used with wave types 0,1,4.  Now those wave types repeat the waveparam value in the [-1..1] range, so it always looks good.
+    -fixed preset list selected pos after preset delete
+    -found and fixed bug with custom wave/shape import
+    -Fixes to documentation, driver link updates, etc.
+    -Fixed bug with the 'texture wrap' and 'sustain level' menu items'
+        visibility (...they should, and now only do, show if the current preset 
+        doesn't use pixel shaders).
+    -fixed bug with 'edit sprites' and 'edit custom messages' buttons on the config
+        panel - they were trying to edit the milkdrop 1.0 ini files (milk_*.ini 
+        rather than milk2_*.ini). 
+    -fixed bug with desktop mode - when paused, if you dragged the mouse around
+        on the desktop, milkdrop would update [new] frames instead of just redrawing
+        the exact same last [paused] frame.
+    -fixed bug with desktop mode - if you made winamp run just in the systray,
+        then ran MD2 in desktop mode, then minimized winamp to the systray,
+        then used a global hotkey to pause the song, then clicked on some
+        random window (say, calc.exe) and then clicked back on milkdrop,
+        the taskbar would disappear.  This no longer happens because the
+        viz window, in desktop mode, now only covers the visible portion
+        of the desktop, and not the area occupied by the taskbar.
+    -docs: updated links & text for drivers section
+    
+2.0 - 10 October 2007 (bundled with winamp 5.5)
+    -MilkDrop has been upgraded from DirectX 8 to DirectX 9.
+    -This means it now supports Pixel Shaders.
+      -Each preset can now have two shaders in it: a warp shader
+        and a composite shader.
+      -The "warp" shader performs the frame-to-frame image-warping operation.
+      -The "composite" shader performs the final display of the feedback
+        image to the user.  
+      -See the preset authoring guide for more information.        
+    -Added a "back" button for presets!  You can now use the 'backspace' key 
+      to go back to up to 64 presets that recently played.
+    -Presets can now load textures (jpg, png, etc.) from disk and use them
+      (in shaders) for whatever they want.
+    -Also added several built-in 2D and 3D procedural noise textures.
+    -You can edit the warp & composite shaders on-screen.  
+    -Per-pixel equations have been renamed to per-vertex equations, because
+      that's what they really were.  These equations determine how each point
+      moves - on a big grid that covers the screen.  For all the pixels in between,
+      the motion was interpolated.  Now, that motion data comes into the warp
+      shader as a "uv" coordinate, and you can use it like before, or you can
+      do more work on top of it - but because the pixel shader truly executes
+      (independently) on each pixel, the warp shader truly operates at a "per-pixel"
+      resolution.
+    -When editing per You can now copy and paste to and from the *Windows* clipboard.
+      CTRL+C copy
+      CTRL+X cut
+      CTRL+V paste
+		-The internal canvas (texture) size is no longer locked to power-of-2 squares;
+			it can now match the window size perfectly (...or you can override it
+			to use the old NP2 method).
+		-Max gridsize is up from 128 to 192.
+		-Added 'A' key (aggregate) - loads a random preset, then loads the warp shader 
+		  from another random preset, and then loads the composite shader from
+		  a third random preset.
+		-Added 'D' key - cycles between various lock-states for the warp and
+      composite shaders.  When one of these shaders is locked,
+      loading a new preset will load everything *except* the
+      locked shaders, creating a mix between the two presets.
+    -Ditched 'stereo 3D' mode.  It never worked that well anyway.
+    -Added "aspectx" and "aspecty" (read-only) to per-frame and per-vertex variables,
+      to help presets deal with widescreen display modes properly.
+      Multiply an X,Y coord by these to make it fit the window properly.
+    -The q1-q8 variables have been expanded; the range is now q1-q32.
+    
+1.04L - 04 May 2007	
+        -added localization support
+        -fixed Milkdrop DEP incompatibility
+        -fixed theming of preferences under XP+
+	   
+1.04d - 13 February 2007
+        -fixed some multi-user issues 
+		
+1.04c - 21 June 2006
+        -added missing files to Winamp installer
+        -added multi user support
+        -fixed 100% cpu usage when paused
+        -added over 200 new Milkdrop presets to Winamp installer!
+
+
+1.04b - 10 October 2003
+        -slimmed down the presets for bundling w/Winamp 5
+        -fixed blurry text when running in wa5 w/skinning, 
+            before first window resize
+        -can now start plugin w/o music (Winamp 5+)
+        -(hopefully Justin shrank the DLL some, too)
+
+1.04 - 31 July 2003
+        -upgraded to VMS (VisMegaSDK) 1.05 and DirectX 8.  That means a revolutionized 
+            Desktop Mode, better driver support, better multimon support, winamp
+            skinning (when running in windowed mode), increased general stability, 
+            and much, much more.
+        -added CUSTOM SHAPES and CUSTOM WAVEFORMS.            
+        -added the following variables for per-frame scripting: (all booleans, except 
+            'gamma') wave_usedots, wave_thick, wave_additive, wave_brighten
+            gamma, darken_center, wrap, invert, brighten, darken, solarize
+            (also, note that echo_zoom, echo_alpha, and echo_orient were already in there,
+             but weren't covered in the documentation!)
+        -added 'meshx' and 'meshy' [read-only] variables to the preset init, per-frame, 
+            and per-pixel equations
+        -cranked max. mesh size up to 128x96
+        -added alphanumeric seeking to the playlist; while playlist is up,
+            you can now press A-Z and 0-9 to seek to the next song in the playlist
+            that starts with that character.  SHIFT+A-Z seeks upward (while lowercase/
+            regular a-z seeks downward).
+        -added some options to config panel
+        -sprites & custom messages: added 'kill' keys
+            -CTRL+K kills all running sprites
+            -CTRL+T kills current song title anim
+            -CTRL+Y kills current custom message
+        -sprites:
+            -for sprites, color key can't be a range anymore; it's
+                now limited to just a single color.  'colorkey_lo' and 
+                'colorkey_hi' have been replaced with just one setting, 
+                'colorkey'.
+            -also, behavior of the 'burn' variable has changed; now,
+                a sprite can be burned in on any frame, not just on the
+                last frame before it dies.  See the sample sprite config
+                file, milk_img.ini, for more information.
+        -preset ratings are no longer read in all at once; instead, they are scanned in
+            1 per frame until they're all in.  This fixes the long pauses when you switch
+            to a directory that has many hundreds of presets.  If you want to switch
+            back to the old way (read them all in at once), there is an option for it
+            in the config panel.
+        -internal texture size now has a little more bias toward a finer texture, 
+            based on the window size, when set to 'Auto'.  (Before, for example,
+            to reach 1024x1024, the window had to be 768x768 or greater; now, it
+            only has to be 640x640 (25% of the way there).  I adjusted it because
+            before, at in-between resolutions like 767x767, it looked very grainy;
+            now it will always look nice and crisp, at any window size, but still
+            won't cause too much aliasing (due to downsampling for display).
+        -..and much many massive amounts of more!
+
+1.03 final - 19 June 2002
+        -fixed bug with motion vectors; when there were 64 of them on X
+            and 48 and Y (the upper limits), stray lines would sometimes
+            be drawn along the top and right edges of the screen.
+        -revamped the help screen
+        -added some cool new presets
+        -touched up the documentation
+
+1.03 beta 3 - 15 May 2002
+        -letter 'g' no longer gets cut off in custom messages
+        -(oops... it's 'wave_mode', not 'wave_type'.)
+        -fixed 'q1'..'q8' in the preset init code.
+        -revamped the way presets are loaded & blended; transitions
+            should be cleaner now.  
+        -made motion vectors morph more smoothly during transitions;
+            if the old preset had motion vectors on but the new one
+            doesn't, then the #, drift speed, length, and color 
+            of motion vectors does not change as they fade out; 
+            and vice versa if the mv's are fading in.
+        -added optional 'burn-in' for sprites, so when they are finished, 
+            they leave an imprint in the background.  The sprite will
+            burn into the background at the end of its lifetime 
+            if the variable 'burn' is set to a nonzero value; if 'burn'
+            is zero, the sprite will not burn in.
+        -motion vectors: reverted to 1.02 functionality, following 
+            krash's advice.  So mv's should now be backwards-compatible 
+            (with 1.02 versions and earlier).  Now, dx and dy are constant
+            offsets for the motion vectors; if you want them to scroll,
+            alter dx and dy based on the time (or frame).
+        -finished writing critical notes in milk_img.ini.
+        -revamped the keyboard interface for custom messages & sprites.
+            see the documentation.  The realtime help screen won't
+            provide too useful, though (not enough space to lay it all
+            down there).
+                
+1.03 beta 2 - 1 May 2002
+        -preset comments are in; start them with '//' anywhere on the line,
+          and the rest of the line will be ignored.
+        -added variables:
+            -fps (read-only)
+            -video echo options: echo_zoom (0..1..+inf), echo_alpha (0..1), 
+                echo_orient (0,1,2,3)
+            -motion vector drift: mv_dx, mv_dy (a la geiss)
+            -wave_mode[0-7], wave_a(0..?)
+        -fixed texel alignment
+            -nVidia: dx|dy += -1/(texsize*2)    
+            -same for:         http://forums.winamp.com/showthread.php?threadid=83401 
+                All nVidia Cards (Many confirmed tested), 
+                3dfx Voodoo Cards (Voodoo 3 confirmed tested), 
+                ATI Cards (ATI All-In-Wonder confirmed Tested) 
+                Kyro II Confirmed Tested 
+                even Illusion's antiquated Intel Card needs it. 
+            -(untested: the matrox cards)
+            -super thanks to Rovastar for researching & cracking this one
+        -added option for thicker waves; see wave menu.
+            -note: only takes effect when texture size is >= 512x512!
+        -modified presets for new texel alignment fix:
+            -Zylot - Tunnel of Illusion
+            -Zylot - S. Pulse Virus
+            -Most of Krash' s presets
+            -Illusion and Rovastar - Grand Odyssey Mod
+            -Unchained: Goo Kung Foo and Perverted dialect.
+            -optimized some, thanks to Rovastar for pointing out lines in
+                per-pixel code that could be migrated into per-frame code.
+            -many of my own: made waveforms thick
+        -some new presets
+            -(bipolar 4,5; supernova 2; calligraphy; others from milkdrop.co.uk)
+        -fixed bug with sound analysis where sound variables in expressions
+            (bass, bass_att, treb, etc.) could be NAN on the first frame
+            that milkdrop ran.  (symptoms could be bad if the value was
+            used over & over in subsequent frames!)
+        -saved about 100k on the installer by updating to NSIS 1.98 and
+            using the new bzip2 compression. (thanks again to rovastar)
+        -made the texture used for song titles & custom messages take 1/4
+            as much video memory (was square before, blech - now it tries
+            4:1; if that fails it tries 2:1; then 1:1 as a last resort.)
+        -added config panel option to mute all errors/warnings that might 
+            appear in the upper-right corner.
+        -revamped the configuration for desktop mode w/software blit.  
+            Now, you have a choice of 3 different ways to bring the image 
+            across the bus (from video to system memory).  Then the image
+            is converted from RGB to YUV on the cpu, and then you also get
+            to select how to send the image across the bus again, back to
+            video memory, for display on the desktop.  The 3 methods are
+            1) copy the data using an mmx-accelerated memory copy routine
+                (never-fail cornbread)
+            2) use directx to blit from one surface to another 
+                (sometimes drivers flake out on this)
+            3) skip it; read/write directly to/from video memory
+                (never-fail cornbread)
+            Regarding 1 vs. 3: they'll both always work; usually #1 is
+            faster going from video to system memory, and #3 is faster
+            going from system back to video; but not always.  Try different
+            combinations out on your card and see what happens.
+        -sprites!
+            users can edit 'milk_img.ini' and write their own code to control
+            the sprites.  Each sprite is an instance of a jpeg image from disk,
+            displayed according to the code in the .ini file.  Up to 16 sprites 
+            can be running at once.  
+        -stole Y + K keys for use with custom messages & sprites.
+            Hit 'y' to enter custom message mode, then enter two-digit
+            codes to launch custom messages.  Hit 'k' to enter sprite
+            mode, then enter three-digit codes to launch sprites.
+        -added 'preset initialization code', so you can initialize
+            your custom variables when the preset is first loaded.
+        -increased number of 'q' variables from 5 to 8.  (q1..q8 are
+            used to carry values from the per-frame equations to the
+            per-pixel equations.  Note that they can now also carry
+            values from the preset init equations, on to the per-frame
+            AND per-pixel equations!)
+		-automated the brightness slider in the config panel; now there's
+			a checkbox that says, 'guess, based on my video card'.  Currently,
+			the auto-brightness algorithm is simple: if you have an nVidia
+			card, it will set it to 2; otherwise, it sets it to 0.
+        
+1.02 - 2/7/02
+        -added CUSTOM MESSAGES - you can edit them in the file MILK_MSG.INI in your
+            WINAMP\PLUGINS directory.  They are displayed by either keying in their
+            2-digit numerical code ('##') at runtime, or randomly if you choose this
+            option from the config panel (see the 'More Options' dialog).
+        -also added RANDOMIZATION FOR SONG TITLE ANIMATIONS (also see the 'More 
+            Options' dialog from the config panel).
+        -added INSTANT HARD CUT HOTKEY: 'H'
+        -for preset authors:
+            -per_frame and per_pixel code use to get cut off if they didn't fit 
+                on the screen; this is now fixed (flips to next page as needed)
+            -when editing per-frame/per-pixel equations, the line that the cursor 
+                is on is now highlighted!
+            -fixed an old bug where if the per-pixel or per-frame code had nothing 
+                in it except spaces & linefeeds, it would display an error message 
+                saying "error in per-{pixel|frame} code".
+            -added a 'trail length' parameter to the motion vectors. 
+            -added a bunch of per-frame variables to control the motion vectors: 
+                mv_x, mv_y, mv_l, mv_r, mv_g, mv_b, mv_a.  Also got rid of the 
+                motion vectors on/off setting; now the opacity controls this.
+            -cranked up max. # of user variables from 23 to 33.  (Added 16 slots, 
+                but used 6 of them for motion vectors.)
+            -added a per-frame variable called 'monitor'.  Set the value of this 
+                variable in the per-frame code, and then press 'N' to monitor (show) 
+                its value in the top-right corner of the screen.  Should be very 
+                useful for debugging.  (Thanks to Krash for the great suggestion 
+                on how to implement this!)
+            -added the int() function, which turns the argument into an integer 
+                (whole number).  Rounding is toward zero.  Examples: 
+                    int(-1.1) -> -1, int(-1) -> -1, int(-0.9) -> 0;
+                    int(0.9) -> 0, int (1.0) -> 1, int(1.1) -> 1;
+                    int (2.1) -> 2.
+        -improved 3D mode:
+            -drastically improved quality of stereo 3D images by changing default 
+                3d colors to CYAN (full green + blue; was just full blue) for the 
+                left eye and RED for the right eye.  It turns out that this provides 
+                an equivalent 3d image, but gives you the full range of colors for 
+                all presets, which in turn probably makes the 3Dness more visible 
+                to your brain anyway.
+            -also, when in 3D mode, made the waveforms 60% white and 40% their 
+                original color (used to be 100% white because so much color was lost 
+                in the green channel).
+        -song titles:
+            -(added randomization, as mentioned above)
+            -improved max. resolution of song titles by increasing the max. 
+                allowable GDI font size
+            -fixed longstanding bug with the "burning in" of song titles after 
+                they're done displaying; the old, floating location wouldn't exactly 
+                match where the title would be burned into the background & melt away.
+        -timing & animation:
+            -protected against milkdrop's animation running super-fast because the 
+                clock jumped way ahead when no frames were rendered (i.e. milkdrop 
+                got stalled somehow).
+            -smoothed the animation by assuming the time for each frame to be 80% 
+                of 1/fps and 20% the actual time reported.
+        -misc:
+            -converted ANSI_CHARSET to DEFAULT_CHARSET in CreateFont() calls (should 
+                fix some display of funky/foreign character sets)
+            -added 'R' key to toggle random vs. sequential order for loading presets
+            -fixed alphanumeric sorting of presets (used to have minor errors such 
+                as putting "galaxy 2" before "galaxy", and so forth - unfortunately 
+                this is how strcmp() - even Windows Explorer - sorts them.  I rewrote 
+                strcmp() to make it sort in a more 'natural' order.)
+            -'&' characters in preset filenames no longer show up as an '_' character, 
+                although it still looks funny if you try to save one with an '&' already 
+                in it, but don't worry, it will preserve the '&' (even though it looks 
+                messed up).  Note that you still can't type a *new* '&' into the filename 
+                when you go to save a preset.  It is safe to rename it from outside 
+                MilkDrop, though, and use it in MilkDrop later. 
+            -fixed preset-to-preset blending bugs for the 10 border variables.
+            -fixed a bug in blending from a preset using waveform #7 (two horizontal 
+                waveforms) to waveform #0 (a circular waveform), where the right edge 
+                of the top horizonal wave would get connected (via a straight line) 
+                to the left edge of the bottom horizontal wave, as soon as the blend 
+                began.
+            -m_debug.txt: added some caps detection info at init time; screened out 
+                logging of WM_MOUSEMOVE, WM_NCHITTEST, and WM_SETCURSOR messages.
+            -improved motion vector motion prediction so that the tips of the motion 
+                vectors should be perfectly matched from frame to frame, when the 
+                trail length is set to 1.  **Note that it defaults to 0.9, so that 
+                the look is similar to the old, mismatched version! (so the presets 
+                are backwards compatible.)  **Also note that for video cards that 
+                do not support anti-aliased edges, there could be up to 1 pixel of 
+                error here.  Check m_debug.txt for whether or not your driver/card 
+                supports anti-aliased edges for lines.)
+
+1.01 - 12/7/01
+        -playlist feature ('p' key) no longer crashes on Windows ME/98SE.
+        -fixed problems with ampersand ('&') character in song titles/playlist
+        -fixed bug with previous max. of 23 user variables per session.  (Now, 
+            it's a max of 23 user variables per preset, as it should be.)
+        
+1.0 - 10/30/01
+        -added a section to the documentation on using "line-in" as your 
+            audio source (instead of mp3's)
+        -lowered minimum frame time (enforced by winamp) from 25 ms to 10ms, 
+            so now, the max. possible fps is 100 instead of 40.
+        -tightened A/V sync by 5 ms (raised audio latency from 25 to 30 ms).
+        -fixed &'s in song titles (as displayed when you hit F2)
+        -F7,F8 were switched in the help screen (F1)
+        -when running in desktop mode, if you have a pattern on your windows 
+            background, it gets nuked.  Before, if you had a pattern, the 
+            pattern would remain and you'd only be able to see milkdrop through 
+            the small boxes of your desktop icons' background text.  I didn't 
+            bother restoring the pattern upon exit because I am lazy and assume 
+            that nobody intentionally uses these things anymore.  =)
+        -improved warning message for windowed/desktop modes, when auto-texture-
+            size is scaled down due to insufficient video memory.  It previously 
+            just reported the downsizing, but now, it also recommends that you 
+            drop your color depth to 16 bits (if you haven't already) and that 
+            you try decreasing your screen resolution.
+        -might have fixed a bug with the playlist feature ('p') crashing people's 
+            machines.
+
+0.99g - 9/11/01
+        -added playlist browsing (hit 'p')
+        -added checkbox to fix slow text (finally!)
+        -song titles fixed too (on some cards, they were garbled) (also, in low 
+            video mem. situations, they might have never appeared - that's fixed too)
+        -added checkbox to allow double buffering for desktop mode; default is 
+            UNCHECKED; can provide significant speed boost, but you might see some 
+            tearing during the vertical retrace; if so, enable double-buffering.  
+            It used to always be double-buffered, which is slower, though it is 
+            page-tearing-artifact-free.
+        -added always-on-top option for windowed mode
+        -added "page x of y" footnote to the preset and playlist menus
+        -improved the auto-texture-size management code, so users will be less 
+            likely to get the "couldn't create offscreen surface #1" (or #2) error.  
+            Instead, the textures are continally downsized until there is enough 
+            memory for them.  This might mean blockier images, but at least it will run.
+        -desktop mode can now do software blit when an RGB overlay surface is created. 
+            (before, software blit was really only available for YUV-type overlays.)
+        -desktop mode compatibility improved: more likely to work at higher resolutions now
+        -desktop mode: fixed YUV-type *non-mmx* software blits when Windows is in 16-bit color.  
+            (weren't implemented before; it just assumed windows was in 32-bit color, 
+            and the result would look munged.)
+        -improved mmx memcpy: will now copy as long as the (difference between two 
+            pointers) % 8 is zero.  (before, they both had to be a multiple of 8).
+        -reorganized the config panel; nice
+        -centered the config panel on the screen (by removing winamp as hwndparent - der)
+        -centered the 3 color picker dialogs (by specifying current dialog window 
+            as the parent - der)
+        -(also cleaned up redundant code for color picker dialogs)
+        -super-slight optimizations to speed of waveform blending
+        -tweaked the way the "clear screen at startup" option works, since some 
+            users had problems with it
+        -fixed aspect ratio, so when window is at an extreme AR, it clips the extra 
+            (instead of fitting the image to the window)
+        -fixed a fullscreen lost surface bug introduced in 0.99f that blacked 
+            the screen out if you ALT-TABBED out of milkdrop & returned.
+        -fixed bug where tooltips were lost on some systems (left variable in, 
+            but no way to change it - locked to TRUE for now)
+        -fixed bug where 'try for RGB overlay...' and 'try for YUV overlay...' 
+            checkboxes were disabled when software blit was on.  (Don't know what 
+            I was thinking there!)
+        -tweaked presets; added some cool shift-on-beat effects
+
+0.99f - 8/22/01
+        -added graphical song titles
+        -added screen borders; can be used to create interesting feedback patterns when 
+            zooming out
+        -waveforms now blend smoothly!
+        -finally gave milkdrop an application icon
+        -added 'U' key to toggle winamp's shuffle feature on/off
+        -fixed bug with handling of 'r' key when preset menu is up; now, to rename a file, 
+            use INSERT
+        -fixed a 1-frame-delay bug for warping (caused a lag for audio-driven 'warps')
+        -fixed bug where 'progress' variable's value was always 0 in per-pixel eq's 
+            (thanks rovastar)
+        -removed "F7: show tooltips for menu items" hotkey (needed it for title animations)
+        -removed U, I keys (for warp)
+        -moved T key (for zoom) to I (i=zoom in, I=zoom out) (T is now used for song titles)
+        -speed optimization: now using memcpy_MMX to copy 576*2*4=4608 bytes of sound data 
+            per frame
+        -size optimizations: painstakingly shaved 8k off the .dll
+        -in windowed mode, when a user resizes the window to a size that's too large and 
+            there's not enough video memory and MilkDrop closes, it now resets the size 
+            of the window for the next time you run MilkDrop.  (before it would just try 
+            to start the next time with the same window position/size and keep failing.)
+        -added 'try for RGB overlay before trying YUV-types' checkbox
+        -added 'try for YUY2 overlay surface before trying UYVY' checkbox
+        -added "stereo 3d always on" option (unchecked by default)
+        -added "clear screen at startup" option (checked by default)
+        -made soft cut timer reset on hard cuts
+
+0.99e - 7/5/01
+        -added beat-driven HARD CUTS; very cool
+        -added a VJ mode, where you can make all the text draw in a separate 
+            window instead of to the main graphics display; should be very 
+            handy for concerts
+        -added preset rating; use + and - keys (volume control is only available 
+            w/up,down arrows now); use F6 to show rating of current preset
+        -you can now use any color lenses for left/right stereo vision; just tell 
+            it what color you've got (by speaking aloud)
+        -desktop mode optimization: block copy from video memory is now optional, 
+            because on 5-10% of systems, it actually makes things slower.
+        -transitions between 2 presets both using video echo, but in different 
+            orientations, are now smooth
+        -added 'progress' variable to per-frame and per-pixel equations; tells you 
+            how far through the preset you are (temporally) (0..1), so you can make 
+            gradually-shifting effects
+        -added mystery param to per-frame eq's (variable name is 'wave_mystery')
+        -settings such as showing song titles, times, fps, ratings, tooltips, etc. 
+            are all now preserved from session to session
+        -when Load menu is up, added seeking by typing in first char of name
+             -also disabled left/right arrows when Load menu is up, so music 
+              won't skip on you
+        -windowed mode now remembers the window's final size, position between sessions
+             -safe for 2nd monitor, too
+        -fixed bug with ALT-TABBING in and out of fullscreen mode
+        -fixed bug with vertical spacing of song title/time readout when the fancy 
+            font size was set to anything but "normal"
+        -plugin listing (in Winamp prefs screen) and the window title now show the 
+            version #
+        -fonts now scale with the window
+        -protected against trying to run MilkDrop while the config panel is still open
+        -fixed the 1-pixel-wide garbage that sometimes sat at the right and bottom 
+            edges, in windowed mode
+        -fixed bug where after going to another app, fullscreen, while in Desktop Mode,
+            upon your return from fullscreen the overlay surface was lost (and just sat 
+            there, black).
+        -stopped sending WM_KEYUPs to Winamp (oops; never sent WM_KEYDOWNS to begin 
+            with anyway)
+        -load menu: '[..]' now reads '[..] (parent directory)'
+        -config panel: broke some stuff off into a 'more options' dialog
+
+0.99d - 6/5/01
+        -desktop mode is officially in
+        -added new waveforms
+        -added temporal wave alignment
+        -added fps limiting
+        -added "view documentation" button to config panel
+        -added UP/DOWN keys for volume up/down
+        -improved seeking for CTRL-LEFT, CTRL_RIGHT: now seeks by breaks between groups of 
+            alphabetic characters, instead of just looking for spaces.
+        -added 5 new variables (q1..q5) for passing values from the per-frame to the per-pixel 
+            equations (user-defined variables don't carry over like permanent variables)
+        -added brighten (square root), darken (square), invert, and solarize filters
+        -tweak: made transitions slightly sharper (10% more toward a cosine curve than a 
+            linear curve now)
+        -now setting D3DRENDERSTATE_SHADEMODE to D3DSHADE_GOURAUD (used to be FLAT, 
+            and combined with per-vertex coloration, which seemed to be asking for trouble)
+        -added warning messagebox for if first call to SetRenderTarget fails
+        -fixed bugs with the values of "x" and "y" for per-pixel equations
+                -x: range was -1..1; should have been 0..1
+                -y: range was 0..2; should have been 0..1
+                -(all presets using x,y in their per-pixel equations had to be adjusted)
+        -fixed bug where if the previous preset folder disappeared, you couldn't hit 'L' 
+            to browse to a new folder
+        -fixed a potential bug with dither not being a hardware capability
+        -fixed a bug with scroll lock (didn't reset the LED state when MilkDrop started)
+        -fixed a bug with loading presets with blank lines in the per-frame or per-pixel 
+            equations
+                -(the blank line, and everything after it, would not be read in)
+        -revamped gamma loop
+
+0.99c - 5/21/01
+        -added red-blue stereo; use F9 to toggle it on/off
+            -note: you need those cheesy glasses with the red & blue plastic 
+             lenses for this to work!
+        -added a bunch of 3D presets in the \3D subdir
+        -added the ability to browse the directory structure
+        -added F8 to jump to new directory (or drive)
+        -changed the 'fix pink/white color saturation artifact' checkbox
+            into a simple brightness slider, so you have more freedom with it
+        -"+", "-" keys now work for the numeric keypad and regular keys.
+        -fixed a video memory leak for windowed mode (the manually-created backbuffer wasn't 
+            being released; once you exited winamp, though, the memory was freed)
+        -fixed a bug with closing Winamp while milkdrop was running in windowed mode
+        -fixed a weird bug with hitting ESC from the config panel sometimes doing nothing
+        -fixed a weird bug where when milkdrop was launched in windowed mode, 
+            keystrokes to winamp don't work until you moused-over the winamp window
+
+0.99b - 5/16/01
+        -added windowed mode
+        -added +/- keys for volume control
+        -added SHIFT + left/right arrows to rewind/ffwd 30 seconds
+        -improved various error messages
+        -protected vs. running config panel while MilkDrop is running
+        -protected vs. running milkdrop without music playing
+
+0.99 - 5/11/01
+        -first version
+
+
+return to top
+
+ + diff --git a/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop_preset_authoring.html b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop_preset_authoring.html new file mode 100644 index 0000000..8825d60 --- /dev/null +++ b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/milkdrop_preset_authoring.html @@ -0,0 +1,1990 @@ + + +MilkDrop Preset Authoring Guide + + + +
+
+MILKDROP preset authoring guide
+   return to milkdrop.html
+
+
+
+* * *
+Note that there is another, quite comprehensive, Preset Authoring Guide 
+available on the web at http://www.milkdrop.co.uk/, 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.
+* * *
+
+
+Section Listing
+-----------------------
+1. about presets
+2. preset authoring - basic
+3. preset authoring - advanced
+    a. per-frame equations
+    b. per-vertex equations
+    c. variable pools, declaring your own variables, persistence of values
+    d. preset init code; carrying values between variable pools, using q1-q32
+    e. custom shapes & waves
+    f. pixel shaders
+         conceptual overview
+         the WARP shader
+         the COMPOSITE shader
+         pixel shader reference
+           intrinsic instructions
+           per-vertex shader inputs
+           per-frame shader inputs
+         texture sampling
+           milkdrop's built-in textures - main, blur, and noise
+           blur1, blur2, blur3
+           noise textures
+           reading textures from disk
+           random texture selection
+         misc. cool shader tricks
+         quality assurance for shaders
+    g. quality assurance
+    h. debugging
+    i. function reference (for expressions, not shaders)
+
+
+
+1. About Presets
+-----------------------
+    When you watch MilkDrop, you are watching a series of Presets.  Each
+    one has its own look and feel, draws the sound waves in a particular
+    way, and has certain motions to it.  After some time, you will see
+    a short blend transition, and then you will be watching a new preset.  
+
+    A single '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 over 100 built-in presets, each one having a distinct
+    look and feel to it.  
+    
+    Using MilkDrop's built-in "preset-editing menu" (the M key), you can 
+    edit presets on the fly, on-screen, 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 http://www.nullsoft.com/free/milkdrop and then jump to the
+    "preset sharing forum" to see what other people have come up with,
+    or post your own cool, new presets.  milkdrop.co.uk/ is another great 
+    place to download collections of presets made by others like yourself.
+
+
+
+2. Preset Authoring - Basic
+-----------------------
+
+    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, MilkDrop is sure to move you along to a new (random)
+    preset, over time.  When the menus are showing, the preset is
+    automatically temporarily locked, but BE CAREFUL - if you're not
+    also using SCROLL LOCK, then 0.1 seconds after you hide the menu
+    to take a look at your new masterpiece, MilkDrop might load a 
+    random new preset on you, and you'd lose your changes!  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 **
+        g/G - decrease, increase gamma (brightness) **
+
+    VIDEO ECHO effect **
+        q/Q - scale 2nd graphics layer down/up **
+        F - flip 2nd graphics layer (cycles through 4 fixed orientations) **
+
+    ** these keys only have an effect if you are running a 
+       MilkDrop 1-era preset.  In MilkDrop 2-era presets,
+       these values are embedded in the shader, so you need
+       to go into the composite shader and tweak the code.
+
+
+
+3. Preset Authoring - Advanced
+-----------------------
+
+    This section describes how to use the 'per-frame' and 'per-vertex' 
+    equations to develop unique new presets.
+
+
+    
+    a. PER-FRAME EQUATIONS
+    ----------------------
+    
+    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-vertex' 
+    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.
+    pixelsx        NO     16-4096 width of the viz window, in pixels.  If Canvas Stretch is on, this is the pre-stretched size.  (same as "texsize.x" for shaders)
+    pixelsy        NO     16-4096 height of the viz window, in pixels.  If Canvas Stretch is on, this is the pre-stretched size.  (same as "texsize.y" for shaders)
+    aspectx        NO     >0     multiply an x-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.
+                                   -value: if widescreen, 1; if window is tall, h/w.
+    aspecty        NO     >0     multiply a y-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.
+                                   -value: if widescreen, w/h; if window is tall, 1.
+    
+    blur1_min      yes    0..1   Normally these are set to 0 (min) and 1 (max).
+    blur2_min      yes    0..1   You can clamp the values in the blur texture to a tighter
+    blur3_min      yes    0..1     range, though.  
+    blur1_max      yes    0..1   This will increase the precision in the blur textures,
+    blur2_max      yes    0..1     but you run the risk of clamping values to your min/max.
+    blur3_max      yes    0..1   If you use the GetBlur1() .. GetBlur3() functions to sample
+    blur1_edge_darken yes 0..1     the blur texture, they will automatically "unpack" the
+                                   values for you in the end!
+    
+    q1             yes    any    } Used to carry values along a chain                                         
+    q2             yes    any    }  from the preset init code,                                                
+    q3             yes    any    }  to the preset per-frame code, then on                                     
+    q4             yes    any    }    to the preset per-vertex code;                                          
+    q5             yes    any    }    or to the custom shape per-frame code,                                  
+    q6             yes    any    }    or to the custom wave per-frame code,                                   
+    q7             yes    any    }      then to the custom wave per-vertex code;                              
+    ...                          }    or to the [pixel] shader code.                                          
+    q31            yes    any    } Click here to see a diagram for the Q vars.
+    q32            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-vertex equations; if you set a custom variable's value in the
+    per-frame equations, and try to read it in the per-vertex equations,
+    you will not get the correct value.  Instead, you have to "bridge the
+    gap" using 32 special variables: q1 through q32.  This is usually only
+    used when you want to precompute some custom values in the per-frame 
+    equations for later use in the per-vertex equations (or for use in
+    the pixel shaders).  For a good example of this, see the 'dynamic swirls' 
+    preset.  See below for more information on q1-q32.
+    
+            
+    
+    
+    b. PER-VERTEX EQUATIONS
+    -----------------------
+    
+    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-vertex" equations, instead of per-frame
+    equations.
+    
+    The code for this per-vertex 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-vertex equations are really just like the per-frame equations,
+    except for a variables.  The following variables are available
+    exclusively to per-vertex equations (and not to per-frame equations):
+    
+    NAME   WRITEABLE? 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-192    tells you the user's mesh size in the X direction.  always an integer value.
+    meshy      NO     6-144    tells you the user's mesh size in the Y direction.  always an integer value.
+    pixelsx    NO     16-4096  width of the viz window, in pixels.  If Canvas Stretch is on, this is the pre-stretched size.  (same as "texsize.x" for shaders)
+    pixelsy    NO     16-4096  height of the viz window, in pixels.  If Canvas Stretch is on, this is the pre-stretched size.  (same as "texsize.y" for shaders)
+    aspectx    NO     >0     multiply an x-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.
+                               -value: if widescreen, 1; if window is tall, h/w.
+    aspecty    NO     >0     multiply a y-coordinate by this to make the preset look the same at any aspect (window height:width) ratio.
+                               -value: if widescreen, w/h; if window is tall, 1.
+            
+    q1         yes    any      } Used to carry values along a chain           
+    q2         yes    any      }  from the preset init code,                        
+    q3         yes    any      }  to the preset per-frame code, then on             
+    q4         yes    any      }    to the preset per-vertex code;            
+    q5         yes    any      }    or to the custom shape per-frame code,          
+    q6         yes    any      }    or to the custom wave per-frame code,      
+    q7         yes    any      }      then to the custom wave per-vertex code;
+    ...                        }    or to the [pixel] shader code.            
+    q31        yes    any      } Click here to see a diagram for the Q vars.
+    q32        yes    any      } 
+    
+    
+    The main reason for distinction between per-frame and per-vertex equations
+    is simple: SPEED.  If you have a per-vertex 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-vertex; 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-vertex 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-vertex equations are actually computed.  When you crank this
+    option up, you start eating up CPU cycles rather quickly.
+
+
+
+    
+    c. VARIABLE POOLS; DECLARING YOUR OWN VARIABLES; PERSISTENCE OF VALUES
+    -----------------------
+    Declaring and using your own variables is easy - in some bit of code 
+    (init equations, per-frame equations, etc.) you just write something like
+    the following:
+    
+        billy = 5.3;
+    
+    This creates a variable called 'billy' and sets its value to 5.3.  You can
+    then freely read and/or modify the value of 'billy' within that section
+    of code.
+    
+    However, sometimes it is desireable to create (really, initialize) a variable 
+    in an "init" equations, then use and/or update it in the "per-frame" equations.
+    You can always do this, because paired init and per-frame equations
+    share the same variable pool.  In addition, the values of user-defined
+    variables will persist from frame to frame.
+    
+    There are three variable "pools" in MilkDrop:
+
+      1. preset init code + preset per-frame code
+      2. custom wave init + custom wave per-frame code
+      3. custom shape init + custom shape per-frame code
+    
+    So, you can probably guess that if you declare a variable in the preset
+    init code, you can then read it in the preset per-frame code.  You can
+    also write to it (update it), and its value will persist to the next
+    frame.  All three pools work this way.
+
+    As explained, though, you can't read the value of 'billy' in when in another 
+    variable pool.  (This is intentional, and keeps MilkDrop running nice and 
+    fast.)  If you want to pass values around between variable pools, you need 
+    to use a set of special variables: q1, q2, q3, etc. on up to q32.  See
+    the next section for details on how they work and how to properly use them.
+    Just remember: the Q variables (and later, the T variables) are the only ones 
+    that you can use to "jump" between (carry values between) variable pools.
+    
+    You might notice that there are two other types of equations that weren't 
+    listed above.  They are:
+    
+      * preset per-vertex code
+      * custom wave per-point code
+    
+    For these two code sections, persistent values don't really make sense,
+    because there is no way to properly initialize them.  Any user-defined
+    variables in these code sections should just be treated as scratch
+    variables, not persisting from frame to frame, from vertex to vertex,
+    or from point to point (even though technically, they will... but it
+    probably won't be what you want).  The only thing that really makes sense
+    here is when you want to carry values along from point to point as
+    you run the custom wave per-point code; to do this, use q1-q32.  (See
+    the next section for a more detailed explanation.)  
+
+
+
+    
+    d. PRESET INIT CODE; CARRYING VALUES BETWEEN VARIABLE POOLS, USING q1-q32
+    -----------------------
+    As we've just seen, you can't normally pass values around between variable 
+    pools.  However, there is one mechanism for bridging this gap: the 'Q'
+    variables.  They are named q1, q2, q3, and so on, through q32.  Their
+    main function is to bridge the gap between various variable pools.
+    
+    In MilkDrop 1.03 and later, you can write code that is executed only once,
+    when a preset is loaded (switched to).  This 'preset initialization' code 
+    does two useful things:
+      
+      1. It allows you to set the initial value of your own (user-defined) 
+         variables (such as 'my_variable'), as just explained.  
+         
+      2. It allows you to write the default ("sticky") values for q1, q2, q3... 
+         through q32.  Whatever these values end up at after the init code, 
+         those are the values that q1-q32 will be reset to at the start of 
+         each frame (...the input to the per-frame equations).  If the
+         per-frame equations change the values of q1-q32, those new values will
+         propagate on to other variable pools (see the diagram below), but on
+         the next frame, the values will be reset to the original "sticky" 
+         defaults.
+         
+    See the flow chart below for a brief, and complete, glance at how the values
+    of the Q variables flow throughout MilkDrop.
+    
+    
+    Let's walk through the flow of the chart.  
+    
+    If you write to the values of q1..q32 from the "preset init code", the values 
+    you write will become the new 'base values' to which q1..q32 are initialized 
+    at the start of each frame, for the per-frame code.  So when you access (read) 
+    q1-q32 in the per-frame code, you'll get the values that were *initially* set -
+    over and over, every frame.  You can then modify them (or not) in the per-frame 
+    code, and the (possibly modified values) will then be readable by the per-vertex 
+    code - as well as by all pixel shader code, and others.  However, any modified 
+    values 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.
+
+    In the per-vertex code, the q1-q32 values start (for the first vertex 
+    in any frame) as the values they had at the end of the per-frame code.  If you 
+    modify q1-q32 in the per-vertex code, those modified values will carry over 
+    from vertex to vertex.  (This isn't a very desireable effect; you should avoid 
+    writing to the Q variables from the per-vertex equations.)  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... look at that, 
+    and you'll just get it.)
+
+    There is one trick here.  You might notice that the custom wave/shape
+    init boxes are missing from the diagram.  That's because the q
+    variables coming out of them don't go anywhere.  The Q values that come
+    into the per-frame wave/shape equations come from the preset per-frame
+    equations, as you can see.  But, just to humor you: in the wave/shape init code, 
+    the Q values coming in are the results from the preset init code.  Any Q values 
+    you write to there (in the wave/shape init code) will be meaningless; although
+    you can write to (initialize) your own custom variables, and read those in 
+    later, in the wave/shape per-frame equations!  So, really, you can still route
+    data that way, if you really want to.
+        
+    Side 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-vertex 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-vertex code and want to re-execute the initialization
+    code (i.e. to randomize it or reset the preset), you'll have to save the preset
+    and then re-load it.
+
+    (Historical note: nothing here has changed since MilkDrop 1; these diagrams were
+    just re-designed to be much simpler to read.  Actually, there was a bug in 
+    the old diagrams that is now fixed: on frame 0, they showed the Q values 
+    going straight from the (frame 0!?) per-frame code, into the custom 
+    wave/shape init code.  On frame 0, those Q values actually come straight from 
+    the preset init code.  HOWEVER, they are virtually useless, as discussed above.)
+
+
+
+    
+    e. CUSTOM SHAPES AND WAVES
+    ----------------------
+    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.  You are limited to
+    four custom shapes per preset, however, each one of those can be instanced,
+    which lets you draw a huge number (up to 1024) of them each frame, if you 
+    want to, and each one can be totally different (as long as the value of
+    the 'instance' variable ends up influencing the other properties).
+    
+    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-q32 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-q32 - 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 q_vars.gif image 
+    for a diagram of the flow of the values of the q1-q32 varibles.
+
+    For custom waves and shapes, you can modify q1-q32, if you like, in the per-
+    frame equations.  As usual, the values of the Q variables will not persist 
+    from frame to frame, though - they are reset on each new frame, to match
+    the values they had at the end of the *preset's* per-frame code, this frame. 
+    
+    For custom waves, you also have one more link in the chain: per-point
+    (aka per-vertex) code.  This code is executed once for each data point in the 
+    waveform.  The initial values of q1-q32 coming in (for the first point)
+    are the values that stood at the end of the custom wave per-frame code,
+    this frame.  If you then modify q1-q32 in the per-point code (or even if you
+    don't), the values will pass on to the next point.  You could, for example, 
+    smooth out a waveform using this.
+
+    THE 'T' VARIABLES
+    ----------------------
+    There are 8 additional variables available for custom waves and shapes:
+    t1-t8.  These are very similar to the Q variables, but they exist only
+    for custom waves & shapes.  To see how the data flows from variable pool
+    to variable pool for the T vars, take a look at the diagram below.  Like
+    the Q variables, they exist to help you bridge some gaps between variable
+    pools.  However, the T variables are a bit simpler to understand than the 
+    Q's.  The diagram below should explain it all.
+    
+    
+    
+
+
+    CUSTOM SHAPE PER-FRAME VARIABLES
+    ----------------------
+        NAME    WRITABLE? RANGE    DESCRIPTION
+        ----    --------- -----    -----------                                                                   
+        num_inst   no     1-1024   The total # of instances (the number of times to repeat the per-frame equations for, & draw, this shape).
+        instance   no     0..num_inst-1   The current instance number that the equations are being executed for.
+        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      } Used to carry values along a chain                                         
+        q2         yes    any      }  from the preset init code,                                                
+        q3         yes    any      }  to the preset per-frame code, then on                                     
+        q4         yes    any      }    to the preset per-vertex code;                                          
+        q5         yes    any      }    or to the custom shape per-frame code,                                  
+        q6         yes    any      }    or to the custom wave per-frame code,                                   
+        q7         yes    any      }      then to the custom wave per-vertex code;                              
+        ...                        }    or to the [pixel] shader code.                                          
+        q31        yes    any      } Click here to see a diagram for the Q vars.
+        q32        yes    any      } 
+
+        t1         yes    any      } Used to carry information                                                  
+        t2         yes    any      }  from the custom shape init code                                           
+        t3         yes    any      }    to the custom shape per-frame code.                                       
+        t4         yes    any      } Click here to see a diagram for the T vars.
+        t5         yes    any      } 
+        t6         yes    any      } 
+        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
+        samples    yes    0-512    read: retrieves the # of samples specified for this custom wave (from the menu).
+                                   write: lets you dynamically change that #, frame to frame.
+
+        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      } Used to carry values along a chain                                         
+        q2         yes    any      }  from the preset init code,                                                
+        q3         yes    any      }  to the preset per-frame code, then on                                     
+        q4         yes    any      }    to the preset per-vertex code;                                          
+        q5         yes    any      }    or to the custom shape per-frame code,                                  
+        q6         yes    any      }    or to the custom wave per-frame code,                                   
+        q7         yes    any      }      then to the custom wave per-vertex code;                              
+        ...                        }    or to the [pixel] shader code.                                          
+        q31        yes    any      } Click here to see a diagram for the Q vars.
+        q32        yes    any      } 
+    
+        t1         yes    any      } Used to carry information                                                  
+        t2         yes    any      }  from the custom wave init code,                                           
+        t3         yes    any      }    to the custom wave per-frame code,                                      
+        t4         yes    any      }      then on to the custom wave per-point code                             
+        t5         yes    any      }      (and from point to point, too, if you write                           
+        t6         yes    any      }      to the values from the per-point equations).                          
+        t7         yes    any      } Click here to see a diagram for the T vars.
+        t8         yes    any      } 
+    
+       
+    CUSTOM WAVE PER-POINT (aka PER-VERTEX) 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      } Used to carry values along a chain                                         
+        q2         yes    any      }  from the preset init code,                                                
+        q3         yes    any      }  to the preset per-frame code, then on                                     
+        q4         yes    any      }    to the preset per-vertex code;                                          
+        q5         yes    any      }    or to the custom shape per-frame code,                                  
+        q6         yes    any      }    or to the custom wave per-frame code,                                   
+        q7         yes    any      }      then to the custom wave per-vertex code;                              
+        ...                        }    or to the [pixel] shader code.                                          
+        q31        yes    any      } Click here to see a diagram for the Q vars.
+        q32        yes    any      } 
+
+        t1         yes    any      } Used to carry information                      
+        t2         yes    any      }  from the custom wave init code,               
+        t3         yes    any      }    to the custom wave per-frame code,          
+        t4         yes    any      }      then on to the custom wave per-point code
+        t5         yes    any      }      (and from point to point, too, if you write
+        t6         yes    any      }      to the values from the per-point equations).
+        t7         yes    any      } Click here to see a diagram for the T vars.
+        t8         yes    any      } 
+
+       
+
+    
+    f. PIXEL SHADERS
+    ----------------------
+    The world of realtime computer graphics made a huge stride around 2002-2003,
+    with the advent of pixel shaders.  Lots of people want to learn how to
+    use pixel shaders; writing presets for MilkDrop is a great way 
+    to learn them, because you get to see the effects of your code instantly,
+    on the screen.
+    
+    MilkDrop 1 ran on what is called the "fixed function" graphics pipeline.
+    That meant that certain common graphics operations - and very few of them -
+    could be executed for each pixel.  You could do a few things - maybe multiply
+    by a texture or a color, then maybe one more simple operation - but that was about it.  
+    
+    Newer presets (MilkDrop 2 and later) can take advantage of programmable 
+    pixel shaders.  GPUs (graphics processing units) are now capable of
+    executing dozens, even thousands (on more expensive hardware) of instructions 
+    per pixel.  To tell the GPU what to do at each pixel, you write some code
+    called a "pixel shader".  It looks a lot like C, except you'll see 
+    the types float3 (...often representing a color, or maybe a 3D coordinate), 
+    as well as float2 and float4, as often as you'll see the simple 
+    "float" type.  There is also a lot of emphasis on sampling from textures.
+    Textures can either be procedural (like the image from the previous
+    frame, or a nicely gaussian-blurred version of it, or a procedurally-
+    generated noise texture), or they can be loaded from disk.  To sample
+    from a texture on disk (...but cached in video memory, of course), 
+    in the shader, you simply specify the name of the image file you want to load,
+    and how you want to sample it (what kind of filtering & wrapping) as well as
+    where (the UV coordinates, like XY coordinates, always in the [0..1] range).
+    It reads the sample (as a float4 - some image formats have four channels
+    instead of just r/g/b).  You can then do whatever you like (mathematically)
+    with that sample, take other samples, combine them, and so on.  The final
+    output of the shader is always a color value, and it is this color value
+    that is written to the render target (an internal texture, or the screen).
+    
+    
+    
+    SHADER MODELS - 2.0, 3.0, etc.
+    ------------------------------
+    Since pixel shaders were born, there have been a few revisions.  Each new
+    model has more capabilities than the last.  
+    
+    MilkDrop 1 only supports fixed-function graphics - i.e. no pixel shaders.
+    MilkDrop 2 supports shader model 2 at the lowest level.  (If your GPU
+    doesn't support this, MilkDrop 2 should still run - it just won't show
+    you any presets that use pixel shaders.)  Shader model 2 has a limit of
+    64 instructions (per shader), though.  
+    
+    Presets can be authored to use Shader Model 3, however.  This shader
+    model is not as widely supported (...so be careful writing presets for
+    it - half of the GPUs out there don't support it yet, so the preset
+    won't show up in the preset list on those computers).  However, it is
+    much more powerful, with a virtually unlimited number of instructions.
+    (You're just limited by the speed of your GPU and the number of pixels
+    you need to draw each frame!)  On a GeForce 8000-series, believe it
+    or not, you can easily achieve smooth framerates running shaders with 
+    THOUSANDS of instructions!
+    
+    Shader Model 4.0 also exists, but only in DirectX 10; and DirectX 10
+    is only available with Windows Vista.  Because not many people have
+    Vista yet, we've decided to wait (a damn long time) until going down
+    that path.  Shader Model 3 has virtually everything we need in it
+    anyway.  
+
+
+
+    PRESET FILE VERSIONS & COMPATIBILITY
+    ------------------------------------
+    Note that if you load a MilkDrop 1 preset, you can save it back to disk
+    (even after changing code, variables, etc.) and it will still be readable
+    by MilkDrop 1.  Only if you select the menu option to "Upgrade [its] 
+    Pixel Shader Version" will you be making it no longer backwards-compatible.
+    Once you've done this, though, you'll notice that the menus look slightly
+    different - some new shader-based options will appear, and some old stuff
+    (video echo, gamma, etc. - all things that are now folded into the 
+    composite shader) are all gone.  You'll also notice that two nice little
+    default shaders (warp and composite) have been written for you, and that 
+    the relevant values and options from the old preset (gamma, decay, video 
+    echo, texture wrap, etc.) have all been set correctly in the new shaders, 
+    so that the preset does exactly what it did before.  The only difference 
+    is that now, the preset takes advantage of the full programmability of 
+    pixel shaders (and you have a lot of freedom to tweak it), instead of 
+    being restricted by the highly restrictive DX8 fixed-function graphics 
+    pipeline.
+    
+    Some of the mash-up functions (discussed later) will mix old and new
+    presets together.  In this case, the newly-created preset file will only
+    look correct on MilkDrop 1.xx if it uses neither a warp nor composite shader.
+    It will still run in MilkDrop 1, but without shaders, so whatever random 
+    values gamma, video echo, etc. were left at, will all kick back in.
+
+    One last note: keep in mind that MilkDrop 2 is smart enough to not show
+    you any presets that your GPU can't support.  MilkDrop 1, though, isn't
+    so smart - it will let you look at MilkDrop 2 presets.  It will 
+    ignore all the shader stuff, and probably not display correctly, though.
+
+
+    
+    A PIXEL SHADER - CONCEPTUAL OVERVIEW
+    -------------------------------------
+    Games are what have driven the Hardware Graphics revolution, and games
+    work by projecting many thousands of 3D triangles onto your screen and
+    rasterizing (pixelizing) & shading them.  In MilkDrop, also, 
+    your graphics processing unit (GPU) is told to draw many triangle onto 
+    your screen.  Each is described by three vertices (points).  The interior 
+    of the triangle is a bunch of pixels.  The GPU runs your "shader" code 
+    on each pixel to determine how to shade the pixel - i.e., light it, 
+    or determine its color.  (The terminology is more geared toward the
+    idea that these triangles were originally in 3D and require realistic
+    lighting and shading.)
+    
+    In MilkDrop, the shaders are run on a dumb, regular grid of triangles 
+    that covers the entire visualizer window.  The results of the preset's 
+    per-vertex equations are interpolated across the face of each of these 
+    triangles, and your pixel shader will see the interpolated results.  
+    They come in in the form of "UV" coordinates - they tell you where 
+    to sample (read) the source image, in order to create the desired warping
+    effect each frame - the long-term effect of which is to create perceived
+    motion. 
+    
+    You can then sample that image (or others), do some math on the result,
+    sample some other textures, do some more math, etc.  By the end of 
+    the shader, whatever value is in "ret" (a float3 - three floating-point
+    values) is the color that will be written for that pixel.
+    
+    Each preset in MilkDrop 2 has two pixel shaders: the warp shader,
+    which warps the image from frame to frame, and the composite shader,
+    which draws the frame to the screen (with or without special effects).
+    
+    To edit or experiment with these shaders, while MilkDrop is running, 
+    hit 'M' to view the preset editing menu.  The scroll down to either 
+        [edit warp shader]
+    or 
+        [edit composite shader] 
+    and hit ENTER.  If you don't see either of these options, it means 
+    the current preset is an old MilkDrop 1 preset; in this case, you can 
+    either try a different preset, or you can upgrade the current preset 
+    by selecting 
+
+        update preset's pixel shader version
+
+    toward the bottom of the menu.  Keep in mind that if you upgrade
+    a preset's pixel shader version and then save it to disk, it might 
+    not be usable anymore on other computers with older graphics chips.
+
+    Now go edit one of the two shaders.  Once you're in there, editing,
+    hit F9 - this will toggle the onscreen quick reference for writing
+    shaders.  It's very handy.  Press F9 again to hide it.
+    
+    
+    
+    
+    WARP SHADER
+    ----------------
+    Here is an example of a simple WARP shader.  It is run over every pixel of
+    the internal canvas, with the output being back to the canvas itself (it's
+    a double-buffered texture).  Any special effects that happen here get "baked" 
+    into the image, and will persist into the next frame.
+        
+        shader_body
+        {
+            // sample a pixel from the previous frame.  
+            // uv coord is slightly warped (driven by the per-vertex equations),
+            //   and is what creates the main "movement" in our preset.
+            ret = tex2D( sampler_main, uv ).xyz;
+
+            // darken over time
+            ret *= 0.97;
+        }
+
+    There are only two instructions here... sample the old frame, and 
+    darken the old color value (color values are always in the 0..1 range)
+    to prevent the screen from turning white over time.
+    
+    This code is run on every pixel on the screen.  If the UV's coming in
+    were just [0..1] on X and Y, corresponding exactly to the location of
+    the pixel on the screen, there would be no movement (or warp).  
+    What creates the warp is that the UV coordinates are slightly "off".
+    Each frame, MilkDrop executes the per-vertex equations for the current 
+    preset at all the vertices on a grid covering the screen.  The resulting
+    UV coordinates are then interpolated (by the GPU) between the vertices,
+    and this shader code is executed at each pixel, with the UV coordinates
+    smoothly interpolated for you to do your sampling.  Note that the 
+    original, un-distorted UV coordinates are always available in uv_orig.
+    If the preset had no motion in it, or if we used uv_orig instead of uv, 
+    we would just see pixels getting darker over time, with no apparent motion.
+    
+    Note that MilkDrop's internal canvas (texture) can only store colors
+    in the [0..1] range, so if your shader outputs values beyond that range,
+    the values will be clipped to 0 or 1.  Within the body of the shader,
+    you can go nuts, using any number ranges you want; this restriction only
+    applies to the final output.
+    
+    Note that there are several ways to darken pixels over time, and the 
+    color precision (8 bits per color channel, or 256 shades, or [0..1] 
+    in increments of 0.004) means you have to be careful about darkening 
+    the color over time.  If you're going to darken using this:
+
+        ret *= 0.97;
+
+    then you shouldn't use a multiplier above 0.98, because, due to precision,
+    dark-ish pixels will never become fully dark.  Another way to do it
+    is this: 
+
+        ret -= 0.004;
+
+    The above darkening method will make the pixels go dark, although, 
+    sometimes too quickly.  One way around this is to use error diffusion 
+    dithering (discussed later in this guide).  
+    
+    Probably the best thing is to combine the two:
+
+        ret = (ret - 0.002)*0.99;
+
+    This gives you a partially constant, partially linear darkening effect,
+    and it tends to look the best.  Tweak the values as needed.
+
+    
+    
+    
+    COMPOSITE SHADER
+    ----------------
+    Here is an example of a simple COMPOSITE shader.  It is run over every
+    pixel in the visualizer window, the output being the actual screen that
+    you see.  Anything you do here will NOT affect the subsequent frame - 
+    it will only affect the display of the current frame.
+        
+        shader_body
+        {
+            // sample the corresponding pixel from the internal rendering canvas
+            // note that, here, 'uv' is undistorted.
+            // in the warp shader, 'uv' is warped, and 'uv_orig' is undistorted!
+            ret = tex2D(sampler_main, uv).xyz;
+            
+            // make it a little bit "overbright"
+            ret *= 1.8;
+        }
+
+    The composite shader is easy to understand.  We just sample the
+    internal canvas at the uv coords (undistorted here - but we could
+    play with them if we want!), and manipulate the result if we want
+    (here we brighten it a bit).  The "overbrightening" here is nice because 
+    pixels in the brighter ranges will (for display to the user only)
+    wash out to a white color; however, they can stay that way
+    for a bit.  If we just displayed the color as-is here, and 
+    instead drew our waveforms twice as bright, they would likely
+    start out at white but very quickly fade to shades of grey.
+    
+    Note that we could do other fancy stuff here instead, like:
+            
+            float2 uv_flipped = 1 - uv;    // '1' auto-replicates to float2(1,1)
+            ret = max( tex2D(sampler_main, uv).xyz, 
+                       tex2D(sampler_main, uv_flipped).xyz );
+            ret = pow(ret, float3(0.5, 1, 2));
+            
+    This would flip the image about its diagonal, always show you
+    the brighter pixel from the two orientations, and then ramp
+    the R/G/B channels at different exponents to create a bit of 
+    a cepia color tone.  Not too tough!
+    
+    Now that you have an understanding of what the two shaders do,
+    let's look at all the intrinsic types and operators you can use
+    in shaders.
+   
+    
+    
+    PIXEL SHADER REFERENCE
+    ----------------------
+    Here is a list of all the shader functions and operations at your disposal.
+
+    Data types
+    ----------
+      float       1-4 component full-precision floating-point values.
+      float2        Use these for most things except color values.
+      float3        (When working with UV coords, time values, or big ranges 
+      float4        of values, for example.)
+      
+      half        1-4 component half-precision floating-point values.
+      half2         Much faster on some older hardware; although drivers usually 
+      half3         automatically substitute the 'half' type on you (behind your back) 
+      half4         wherever it is prudent.  Use 'half' for color values, or other 
+                    computations where precision is largely unimportant.
+      
+      float2x2    2d transformation matrix.  (Rotate and/or scale.)
+      float3x2    2d transformation matrix.  (Rotate, scale, translation.)
+      float3x3    3d transformation matrix.  (Rotate and/or scale.)
+      float4x3    3d transformation matrix.  (Rotate, scale, translation.)
+
+    Operators  
+    ----------
+      + - * /     typical arithmetic operators.
+      
+      a += b      same as "a = a + b".  Also valid:  -=  *=  /=
+      
+      ==          equality test.
+      <           less than.
+      <=          less than or equal to.
+      >           greater than.
+      >=          your mom is soo fat.
+      
+      var.x       swizzle operators.  You can stick a dot after any variable
+      var.y       and put up to four letters after it.  If the variable is
+      var.z       a float4, you can choose from x, y, z, and w; if it's a float2,
+      var.w       just x and y; and so on.  The data type yielded can be different 
+      var.xy      than the input, and is determined by the number of letters after 
+      var.wzxy    the dot, and which fields (from the input) you chose.
+      etc.        For example, if you had:
+                    float  alpha = 104.37;
+                    float2 bravo = float2(1,2);
+                    float3 chuck = float3(10,20,30);
+                    float4 delta = float4(5,6,7,8);
+                  Then these swizzles would yield:
+                    alpha.xxx  ->  float3(104.37, 104.37, 104.37)
+                    bravo.yx   ->  float2(2,1)
+                    chuck.z    ->  30
+                    delta.wywy ->  float4(8,6,8,6)
+
+    Preprocessor
+    ------------
+      If you're familiar with C/C++, you can use simple things like
+      #define, #if (condition) / #endif, #if / #elif/#else / #endif, and so on.
+      
+    
+    Intrinsic Instructions
+    ----------------------
+    Unless otherwise noted, these instructions all work on float, float2, float3, 
+    or float4 operands.
+    
+    math operations
+    ---------------
+    abs(a)        Absolute value.  Returns max(a, -a).
+    frac(a)       Fractional value.  Returns (a - (int)a).  (the part after the decimal)
+    floor(a)      Floor.  Returns ((int)a).  (the part before the decimal)
+                    Only works on single floats.
+    saturate(a)   Clamps a to the [0..1] range.  Often FREE (costs no extra instructions).
+    max(a,b)      Returns the greater of each component between a and b.
+    min(a,b)      Returns the lesser of each component between a and b.
+    sqrt(a)       Returns square root of input(s).  Input should be >= 0.  Output always positive.
+    pow(a,b)      Returns a^b.  b can be same type as a, or just a scalar (single float).
+    exp(a)        Returns 2^a.
+    log(a)        Returns log2(a).
+    lerp(a,b,c)   Linear interpolate... blends from a to b based on the value of c[0..1].
+                    (Or extrapolates, if c is outside [0..1] range.)
+                    a and b must be same type; can can be that same type, or just float.
+                    Returns a + c*(b-a).  Return type is same as a and b.
+    dot(a,b)      Dot product.  All versions return A SINGLE FLOAT.
+                    dot(float  a, float  b) returns a+b.
+                    dot(float2 a, float2 b) returns a.x*b.x + a.y*b.y.
+                    dot(float3 a, float3 b) returns a.x*b.x + a.y*b.y + a.z*b.z.
+                    dot(float4 a, float4 b) returns a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w.
+    lum(a)        Converts a color (float3) to greyscale, or "luminance", for the human eye.
+                    Returns dot(a, float3(0.32,0.49,0.29)).
+                    Tip: oversaturate a color using "col = lerp(lum(col), col, 2);"
+    length(a)     Input is float2, float3, or float4 vector; returns the length of the vector.
+                    Returns sqrt(
+    normalize(a)  Input is float2, float3, or float4 vector; normalizes it to unit length (1.0).
+                    Returns a / length(a).
+
+    texture operations
+    ------------------
+    tex2D(sampler_name, uv)  
+                  Samples a 2D texture at the coordinates 'uv', where UV is a float2.
+                    Returns a float4 (r,g,b,alpha).
+    
+    tex3D(sampler_name, uvw)  
+                  Samples a volume (3D) texture at the coordinates 'uvw', where UVW is a float3.
+                  You could use this to sample a built-in "noise volume" or a volume texture 
+                    from a .DDS texture (that holds a 3D texture).
+                    Returns a float4 (r,g,b,alpha).
+
+    GetBlur1(uv)  Samples a slightly-blurred version of the main texture 
+                    (internal canvas).  Input is float2; outputs (returns) a float3.
+    GetBlur2(uv)  Samples a more-blurred version. 
+    GetBlur3(uv)  Samples a very blurry version.
+    
+
+    mega-slow operations
+    --------------------
+    sin(a)        Returns cos(a), where a is in radians.  Output is in -1..1 range.
+                    SLOW - use with care.
+    cos(a)        Returns sin(a), where a is in radians.  Output is in -1..1 range.
+                    SLOW - use with care.
+    atan2(y,x)    Returns the arctangent of y/x.  In english, this means that if you give
+                    it a Y and X coordinate (with the origin at zero), it will tell you
+                    the angle you are at, with respect to the origin.  The signs of x and y 
+                    are used to determine the quadrant of the return values in the range 
+                    [-pi, pi].  atan2 is well-defined for every point other than the origin.
+                    You basically always want to use it like this:
+                        float2 uv2 = (uv-0.5)*aspect.xy;  // widescreen- or 4:3-friendly
+                        float ang = atan2(uv2.y,uv2.x);
+                    SLOW - use with care.
+    mul(a,b)      Multiplies a vector and a matrix together.  You can treat the matrix
+                    as row-major or column-major based on whether you do mul(vec,mat) 
+                    or mul(mat,vec).
+    cross(a,b)    Cross product.  Returns (a.yzx*b.zxy - a.zxy*b.yzx).  
+                    Input and output must be float3's.
+                    Slow - use with care.
+    if (a == b)   'If' blocks work in pixel shaders, although they can be very slow;
+    {               the full code is always executed, whether the branch is taken or not.
+      ...           You can use the equality operator, == (note the two equals signs! 
+    }               very important!) or the >, >=, <, or <= comparators.
+    else 
+    { 
+      ... 
+    }
+         
+    Keep in mind that cos(), sin(), and atan2() are incredibly slow (~8 instructions).  
+    Almost everything else (even divide, taking a reciprocal square root, etc.) is 1 
+    or maybe, at most, 2 instructions.
+              
+    Note that the saturate() instruction, as well as multiplying by 2, 4, or 8, 
+    or dividing by 2, 4, or 8, is a free operation on many GPUs.  And the ALUs
+    inside a GPU almost always do a multiply + add (both) in a single instruction.
+    
+    Also, you can divide by an integer constant without suffixing it with ".0"; 
+    in C/C++, "float x = 1/5;" will give you ZERO; but in shader language, it
+    will give you what you expect: 0.2.
+
+    
+    
+    PER-VERTEX SHADER INPUTS
+    ------------------------
+    
+    Warp shader:
+    
+      float2 uv;          // .xy = warped UV coords, ~[0..1]
+      float2 uv_orig;     // .xy = original (un-warped) UV coords. [0..1]
+      float  rad;         // radius of the current pixel from center of screen [0..1]
+      float  ang;         // angle of the current pixel from center of screen [0..2*PI]
+    
+    Composite shader:
+    
+      float2 uv;          // .xy = [un-warped] UV coords.
+      float  rad;         // radius of the current pixel from center of screen [0..1]
+      float  ang;         // angle of the current pixel from center of screen [0..2*PI]
+      float3 hue_shader;  // .xyz = a color that varies across the screen 
+                          //          (the old 'hue shader' effect from MilkDrop 1).
+    
+    Note that for both shaders, the vertex-interpolated angle value (ang) 
+    gets a bit wonky near the center of the screen, where it is very difficult to 
+    interpolate well (because it wraps suddenly from 0 to PI*2 at 9 o'clock on your 
+    screen).  If you see artifacts due to this, just use
+    
+      float better_ang = atan2(uv.y - 0.5, uv.x - 0.5);
+      
+    It's very slow, but will give you perfect results.  Also, if you want a slightly
+    higher-quality value for the radius, use:
+    
+      float better_rad = length(uv - 0.5);
+      
+    The unwarped UV values will always be of impeccable quality, though, 
+    because they will be interpolated in the direction that they vary, 
+    and the rectilinear mesh is aligned perfectly for this.
+    
+    
+    
+    PER-FRAME SHADER INPUTS
+    -----------------------
+    MilkDrop feeds lots of data into the the shaders.  Here is a list of everything
+    that the shaders can access.
+    
+      float4 rand_preset;  // 4 random floats [0..1], updated once per preset
+      float4 rand_frame;   // 4 random floats [0..1], updated each frame
+      float  time;         // the time, in seconds, starting at zero when the *preset* starts.  
+                           //   (wraps back to zero after 10,000 seconds locked on a single preset.)
+      float  fps;          // the current framerate (frames per second).
+      float  frame;        // the current frame #.
+      float  progress;     // the progress through the current preset.  [0..1]
+      
+      float  bass;         // immediate info about audio levels,
+      float  mid;          //  just like in the per-frame equations,
+      float  treb;         //   etc.
+      float  vol;          // 
+      float  bass_att;     // slightly dampened info about audio levels.
+      float  mid_att;      //  look at bass/bass_att, for example;
+      float  treb_att;     //   if it's >1, then the bass is spiking.
+      float  vol_att;      // 
+      
+      float4 aspect        // .xy: multiplier to use on UV's to paste an image fullscreen, *aspect-aware*; .zw = inverse.
+      float4 texsize       // info about the size of the internal canvas, in pixels.
+                           //   .xy = (width,height); .zw = (1/(float)w, 1/(float)h)
+      
+      // here are some values that roam around in the [0..1] range at varying speeds.
+      float4 slow_roam_cos // .xyzw ~= 0.5 + 0.5*cos(time * float4(~0.005, ~0.008, ~0.013, ~0.022))
+      float4 roam_cos      // .xyzw ~= 0.5 + 0.5*cos(time * float4(~0.3, ~1.3, ~5, ~20))           
+      // here are the corresponding sine values, in case you want them.
+      // pick a cos/sin pair and use the same accessor on it (.x, .z, etc.)
+      // to get plot a point making a circle over time.
+      float4 slow_roam_sin // .xyzw ~= same, but using sin()                                       
+      float4 roam_sin      // .xyzw ~= same, but using sin()                                       
+      // of course, if you want anything more complicated, just generate it
+      // yourself in the per-frame equations, save it in q1-q32, and it will
+      // be available to your shaders!
+
+      float  q1;           // The values of the q1-q32 variables, 
+      float  q2;           //  as output by the preset's per-frame equations.
+      //...                //
+      float  q31;          //
+      float  q32;          //
+      
+      float4 _qa;          // q1-q4    The values of the q1-q32 variables,
+      float4 _qb;          // q5-q8     grouped into float4's 
+      float4 _qc;          // q9-q12     for more convenient access.
+      float4 _qd;          // q13-q16
+      float4 _qe;          // q17-q20
+      float4 _qf;          // q21-q24
+      float4 _qg;          // q25-q28
+      float4 _qh;          // q29-q32
+      
+      float  blur1_min     // these are the values of the min/max
+      float  blur1_max     //  allowable color values for the 3 blur passes,
+      float  blur2_min     //   as set from the onscreen menus.
+      float  blur2_max     //    more info below.
+      float  blur3_min     // 
+      float  blur3_max     // 
+      
+      // note/warning: in general, don't use the current time value
+      // as an input to the *dynamic* rotations; as time gets large,
+      // the results will become total chaos.
+      float4x3 rot_s1;  // four random, static rotations.  
+      float4x3 rot_s2;  //  randomized @ preset load time.
+      float4x3 rot_s3;  //   minor translation component (<1).
+      float4x3 rot_s4;
+      
+      float4x3 rot_d1;  // four random, slowly changing rotations.
+      float4x3 rot_d2;  
+      float4x3 rot_d3;
+      float4x3 rot_d4;
+      
+      float4x3 rot_f1;  // faster-changing.
+      float4x3 rot_f2;
+      float4x3 rot_f3;
+      float4x3 rot_f4;
+      
+      float4x3 rot_vf1;  // very-fast-changing.
+      float4x3 rot_vf2;
+      float4x3 rot_vf3;
+      float4x3 rot_vf4;
+      
+      float4x3 rot_uf1;  // ultra-fast-changing.
+      float4x3 rot_uf2;
+      float4x3 rot_uf3;
+      float4x3 rot_uf4;
+      
+      float4x3 rot_rand1; // random every frame
+      float4x3 rot_rand2;
+      float4x3 rot_rand3;
+      float4x3 rot_rand4;
+
+
+    
+    TEXTURE SAMPLING
+    ----------------
+    We've already used one texture: the internal canvas, also called "Main".
+    Because it's always being used, you don't have to declare it.  You can
+    just sample it.  However, you have some options for how to sample it.
+    There are four samplers tied to the Main canvas:
+      
+                                                 BEHAVIOR OUTSIDE 
+        SAMPLER NAME       FILTERING METHOD      [0..1] UV RANGE
+        ------------       ----------------      ----------------
+        sampler_fw_main*   bilinear filtering    wrap
+        sampler_fc_main    bilinear filtering    clamp
+        sampler_pw_main    point sampling        wrap
+        sampler_pc_main    point sampling        clamp
+        
+        * you can also just use "sampler_main" for this one,
+          since it's by far the most common.
+      
+    When you go to sample a texture, the GPU finds the exact spot
+    in the texture that the UV coordinates point to.  The chances
+    are good that it falls in between 4 texels (pixels) rather than
+    perfectly on one of them.  If you use bilinear filtering to 
+    sample, it will return a properly-weighted average of the four 
+    pixels.  If you use point sampling, it will just return the 
+    nearest single pixel (also called "nearest neighbor").
+    
+    Wrap vs. clamp is also pretty simple: if you specify a UV coord
+    of float2(-0.1, 0.5), the wrap mode would map this to (0.9, 0.5),
+    while the clamp mode would clamp it at (0.0, 0.5).  Wrap mode
+    tends to create tiled images, while clamp mode takes the border
+    color and extends it out infinitely.
+    
+    In general, other textures can be sampled similarly, using these 
+    same two-letter prefixes ("_fw", "_pc", etc.).  Or, you can 
+    always just leave off the prefix, and MilkDrop will assume you 
+    want to do "_fw" - bilinear filtering and wrap mode - the defaults.
+
+    
+    
+    MILKDROP'S BUILT-IN TEXTURES - MAIN, BLUR, and NOISE
+    ----------------------------------------------------
+    MilkDrop has several built-in textures you can sample from.  
+    
+    MAIN
+    ----
+    First, there is the Main texture (the internal canvas).  As already 
+    mentioned, you can sample from it by using sampler_main or one
+    of its variants.
+    
+    
+    BLUR1, BLUR2, BLUR3
+    -------------------
+    Next, there are several blurred versions of the main texture.
+    These are called Blur1, Blur2, and Blur3.  Each one is 
+    progressively blurrier.  You can access them using these special
+    functions: 
+
+        GetBlur1(uv)     // these take a float2 as input
+        GetBlur2(uv)     // & return a float3 color value
+        GetBlur3(uv)    
+        
+    GetBlur1 returns a slightly blurred image, GetBlur2 a more blurry image, 
+    and GetBlur3 an extremely blurry image.  A call to one of the GetBlur 
+    functions is very fast, but keep in mind that the blur textures are only 
+    generated each frame if the shaders actually use them, and the results
+    find their way into the final output color value of the pixel shader!
+    Blur1 is the fastest to generate; then Blur2 (because it is generated
+    from Blur1); and finally, Blur3 is the slowest (generated from Blur2).    
+    
+    Here is an example of how to use one:
+    
+        float3 blurry = GetBlur2(uv);
+    
+    You could add this to your sample from the Main texture to
+    produce a softer-looking image, for example.  Or, you could
+    do an edge detect in the composite shader, by taking the 
+    [absolute value of the] difference between the crisp and blurred
+    main textures:
+    
+        float3 crisp = tex2D(sampler_main, uv).xyz;
+        float3 blurry = GetBlur1(uv);
+        ret = abs( crisp - blurry )*4;
+    
+    The "skin dots" effect in some of the presets (it makes spots 
+    and stripes like you might see on fish or leopards, in nature)
+    is based on a very mild edge-detect in the *warp* shader,
+    and uses it to enforce a certain amount of variance in the 
+    color values.  It also serves to break up large areas of solid
+    white pixels.
+    
+    Note that you can do some cool glow effects by raising the
+    "min" values above 0.  Say, for example, you set blur1_min
+    to 0.5.  That means that any pixels with color values below 
+    0.5 will get clipped to 0.5.  So, when you call GetBlur1(),
+    it's going to give you values in the range [0.5 .. 1.0].  
+    However, because you were only using half the range of possible
+    values, the precision of these values will be twice as good.
+    That's the purpose of the min/max values.  Watch out, though -
+    having your values clipped to a minimum of 0.5 would look bad
+    if you actually had colors that are over 0.5, and you're not 
+    subtracting that 0.5 off.
+    
+    However, if you do set a min and then subtract it off, you can 
+    also get some great glow effects, where only really
+    bright pixels contribute to the "glow"  If you set the min to 
+    0.7, for example, and then sample like this:
+        
+        ret += (GetBlur1(uv) - blur1_min)*2;
+        
+    It will subtract off the 0.7 minimum threshold, but because
+    of the clipping, you will basically just see the bright
+    pixels "glowing".  The *2 is just for a little extra glow.
+    
+    
+    
+    
+    NOISE TEXTURES
+    --------------
+    There are also "noise" (random value) textures built in to MilkDrop.  
+    They are generated when MilkDrop starts, but only so the large amount
+    of (random) data wouldn't bloat the size of the MilkDrop download.
+    They vary in the quality (smoothness) of the noise, as well as
+    how often the pattern repeats itself.  Always use the smallest
+    possible noise texture (_lite or _lq versions) when possible.
+    
+    Here are the details on the six textures:
+    
+    NAME           DIMS  PIXELS    QUALITY
+    ----           ----  ------    ---------
+    noise_lq       2D    256x256   low
+    noise_lq_lite  2D    32x32     low
+    noise_mq       2D    64x64     medium
+    noise_hq       2D    32x32     high
+    noisevol_lq    3D    32x32x32  low
+    noisevol_hq    3D    8x8x8     high
+    
+    Notice that four of them are two-dimensional (use tex2D(float2 uv) 
+    to sample them), and two of them are three-dimensional (use 
+    tex3D(float3 uvw) to sample them).  
+    
+    They come in at various sizes.  You should always use the smallest
+    one necessary, to be video memory cache-friendly!
+    
+    The _lq, _mq, and _hq suffixes denote low, medium, or high quality.
+    The _lq textures have one random value at every texel in the 
+    texture.  But the _mq textures have (generally) about four texels
+    per random value, with high-quality [cubic] filtering baked into the 
+    texture.  (Sometimes you just want something better than bilinear
+    filtering, you know?)  The high-quality textures usually have about
+    8 texels for every random value.  The sizes given here, in pixels,
+    are actually abstractions - they are the conceptual # of pixels
+    (values) before repetition.  In reality, the textures are bigger 
+    (for medium & high quality), and the extra texels are all filled 
+    in using high-quality interpolation.  
+    
+    The higher-quality textures aren't any slower to use, as long as
+    you're sampling them at the right frequency.  If you sample any
+    of these at too high a frequency (i.e. tile them like crazy /
+    multiply the UV's by a large number) your video memory texture
+    cache will bring your GPU to a grinding halt.  Don't do it!
+
+    If using Noise textures with the default sampler settings (filtering 
+    and wrap), you don't need to declare them above the shader_body; they 
+    are always available.  However, if you want to sample them with 
+    special options (clamping or point sampling), then you do have to.  
+    (ex: "sampler sampler_fc_noise_lq", or "sampler_pw_noise_lq").
+    
+    To sample a color value from a noise texture, add code like this:
+    
+        float4 noiseVal = tex2D(sampler_noise_lq, uv_orig );
+        
+    This returns a float4 of values in the [0..1] range.  However, the noise
+    image will be stretched up so the 64x64 pixels cover the screen.  What we'd 
+    really like is to tile it so the noise values map 1:1 to pixels on the
+    screen.  
+    
+    To do this, we need to invoke another handy feature: you can fetch the size 
+    of any texture in MilkDrop.  Just declare a float4 (still outside the shader 
+    body) with the name of the texture, preceded by "texsize_" - like this:
+    
+        float4  texsize_noise_lq;  // .xy = (w,h); .zw = (1/(float)w, 1/(float)h)
+    
+    Also, recall that the size of the Main canvas is universally available to
+    all shaders, and looks like this: (this is auto-declared for you, by the way)
+      
+        float4 texsize       // .xy = (w,h); .zw = (1/(float)w, 1/(float)h)
+    
+    So, if we change our sampling code to look like this:
+    
+        float4 noiseVal = tex2D(sampler_noise_lq, uv_orig*texsize.xy*texsize_noise_lq.zw );
+    
+    It's going to do exactly that.  This is a very common and useful technique.  
+    uv_orig gives you the original (unwarped)
+    UV coordinates [0..1].  If we then multiply by texsize.xy, we get the 
+    pixel number we are on.  For example, if the screen was 1280 x 1024 pixels,
+    we'd get float2 in the range [0..1279, 0..1023].  If we then multiply by
+    texsize_noise_lq.zw, we're dividing by the size of the noise texture,
+    in pixels (this one is 256x256).  So, we'd end up with UV coords roughly 
+    in the range [0..5, 0..4] - our image has been perfect tiled onto the
+    screen, with the pixels displaying 1:1.
+    
+    This can be used to mix a bit of random noise into the image each frame, 
+    which can increase image quality - it's similar to error diffusion 
+    dithering (which is one of the things that set the original Geiss 
+    plugin/screensaver apart from the others, image-quality wise!).   You 
+    can ponder the reasons why.  Also, further adding "rand_frame.xy" to the 
+    UV coords will reposition the noise values every frame, making it seem
+    like truly random [changing] noise:
+    
+        float2 noise_uv = uv_orig*texsize.xy*texsize_noise_lq.zw + rand_frame.xy;
+        float4 noiseVal = tex2D(sampler_noise_lq, noise_uv);
+    
+    To add random dithering (which, statistically, is the same as error-
+    diffusion dithering), try this:
+    
+        float2 uv_noise = uv_orig*texsize.xy*texsize_noise_lq.zw + rand_frame.xy;
+        half4 noiseVal = tex2D(sampler_noise_lq, uv_noise);
+        ret = tex2D(sampler_main, uv);
+        ret += (noiseVal.xyz*2-1) * 0.01;
+        
+    This will add a good deal of noise into the image each frame.  Adding
+    'rand_frame.xy' to the UV coordinate serves to randomly place
+    the noise texture each frame, preventing the noise imprint from being
+    exactly the same each frame, which would cause artifact buildup.
+
+    Important: Note that the medium- and high-quality textures should never be 
+    used for 1:1 mapping! - it is a huge waste.  You will only benefit from their
+    higher quality if you are *zoomed in* on these textures, seeing them
+    magnified, sampling them at a low frequency.  If they are minified 
+    (sampled at a high frequency / zoomed out of) or even displayed at 1:1, 
+    you will thrash your video memory cache and the preset will run very 
+    slow.
+        
+    
+    
+    
+    
+    READING TEXTURES FROM DISK
+    --------------------------
+    Declaring and sampling from your own textures is easy.  First,
+    create your texture.  If you plan on sharing your presets with
+    other people, please make your texture SMALL (256x256 or less)
+    and save it as a JPG file at 95% quality.  The file size should
+    be between 10k and 50k (kilobytes).  Of course, the textures
+    could be huge, crisp photos if you want - they will just be
+    heavy (to send to other people) and will cause a little delay
+    when you switch to a preset that uses them (and loads the texture).  
+    
+    Save the texture to the folder:
+    
+        c:\program files\winamp\plugins\milkdrop2\textures
+        
+    or wherever you installed Winamp and MilkDrop to.  Let's imagine
+    you called your texture billy.jpg.
+    
+    Then, in any shader, above the shader_body section, declare a sampler 
+    for the texture:
+    
+        sampler sampler_billy;
+        
+    That's all you have to do.  It will find the file (billy.jpg)
+    and load it.  Note that the sampler name DOES have to start with 
+    "sampler_", and if you want, you could prefix it with "sampler_pc_" 
+    or "sampler_fw_" (or whatever) to turn on texture clamp and/or point 
+    sampling.  
+    
+    Texture formats supported include: [in order of priority]
+        
+        jpg   (great compression)
+        dds   (a microsoft/directx format - very flexible - can even do 3D)
+        png   (portable network graphics; can give you compress w/an alpha channel)
+        tga   (truevision Targa - 1, 3, or 4 channels)
+        bmp   (puke)
+        dib   (puke)
+        
+    Now that you've declared the texture, you can sample it like this, 
+    from within the shader_body section:
+    
+        float3 mypixel = tex2D(sampler_billy, uv2).xyz;
+        
+    So first it will try to find billy.jpg; then billy.dds; and so
+    on, until it finds a valid texture.  If the texture can not be
+    found in the "milkdrop2\textures" directory, it will then also try
+    to find it **in the current preset directory**; this is done so that
+    preset downloaders can be lazy and just put the presets, along
+    with the textures that come with them, into the same directory.
+    
+    If your shader wants to know how big the texture is, declare this
+    (also above the shader_body section):
+    
+        float4 texsize_billy;    // .xy = (w,h); .zw = (1/w, 1/h)
+        
+    MilkDrop will see the "texsize_" prefix and automatically know what
+    to do.  (You don't have to include the //comment, of course.)
+    
+    To stretch this texture to cover the screen, do this (in the shader
+    body):
+
+        ret = tex2D(sampler_billy, uv).xyz;
+    
+    Or to map it fitted to the screen, aspect-aware:
+    
+        ret = tex2D(sampler_billy, uv * aspect.xy).xyz;
+    
+    Or to tile it so the pixels are represented 1:1:
+    
+        ret = tex2D(sampler_billy, uv * texsize.xy * texsize_billy.zw).xyz;
+        
+    Or to map it tiled exactly 5 times:
+
+        ret = tex2D(sampler_billy, uv * 5).xyz;
+
+    Or to zoom into the center 20% of the image:
+
+        ret = tex2D(sampler_billy, (uv-0.5)*0.2 + 0.5 ).xyz;
+        
+    Of course, you could also declare sampler_pw_billy, to do point
+    sampling, or sampler_fc_billy, for clamping, and so on.
+
+
+
+    
+    RANDOM TEXTURE SELECTION
+    ------------------------
+    You can also load in a random texture.  Just use the name "rand00"
+    through "rand15" as the filename, and MilkDrop will pick a random
+    file and do the rest.  The texsize_ parameters work too.  For example:
+    
+        sampler sampler_rand07;
+        float4  texsize_rand07;
+                
+        shader_body 
+        {    
+          ...
+          float3 color = tex2D(sampler_rand07, uv);
+          ...
+        }
+        
+    You can also choose from random subsets of textures on disk!  Say you
+    have a whole slew of random textures in your textures\ subdirectory,
+    but you have a subset in there that begin with the word "smalltiled".
+    If you specify:
+    
+        sampler sampler_rand02_smalltiled;
+        float4  texsize_rand02;    // ...it's smart enough to get it from just this.
+        
+        shader_body 
+        {    
+          ...
+          float3 color = tex2D(sampler_rand07_smalltiled, uv);
+          ...
+        }
+    
+    Then every time the preset loads (or the shader is recompiled), it's
+    going to pick a new random texture, but it will choose only from the
+    subset of those textures whose names begin with "smalltiled".  
+
+    One last thing, a tip: if you are working in windowed mode (or multimon)
+    and added textures to the directory and haven't yet exited the plugin, 
+    to force the list of textures to update itself, edit one of the shaders 
+    (any shader) and then hit CTRL+ENTER (accept).  That will trigger it
+    to rescan the directory (but only if it needs to, because your shaders
+    ask for random textures).
+
+
+
+    
+    MISC. COOL SHADER TRICKS
+    ------------------------
+    
+        AUTO CENTER DARKENING
+        ---------------------    
+        MilkDrop 1 had a cool feature, "center darken", that would quickly dampen 
+        bright pixels placed at the center of the screen, because in "zoomy" 
+        (forward motion) presets, the screen would quickly become all white
+        if you didn't.  As presets get more sophisticated, though, where the
+        "center" of the zooming motion is can be very hard to pinpoint.
+        
+        You can actually find it algorithmically.  Wherever on the screen you
+        have warped UV coordinates that are very close to the original UV
+        coordinates, it means there's either no motion there, or it's the
+        center of motion - you'll know, based on what kind of preset you're
+        writing.  If it's a "zoomy" preset, it's probably the latter.  In this
+        case, just use something like this in your warp shader:
+        
+            // this darkens the pixels at the center of the zoom, only
+            ret *= 0.97 + 0.03*saturate( length(uv - uv_orig)*200 );  
+
+
+        RANDOM DIFFUSION DITHER
+        -----------------------        
+        See above, in the "noise" section.
+
+       
+        SOFT MAX
+        --------
+        The max(a,b) function returns the max. value for each channel 
+        of the two inputs, however, this can have a discontinuous
+        look sometimes, as it switches from a to b or back suddenly.
+        If you want a not-so-accurate, but smoother, max function,
+        try this:
+        
+            a + b - a*b
+        
+        Note that the inputs must be in the [0..1] range.
+        
+        
+
+    
+    
+    QUALITY ASSURANCE FOR SHADERS
+    -----------------------------
+    *Please* adhere to these guidelines when writing shaders...
+
+      1. use small (256x256 or less) textures; save as jpg 95%
+          -so your presets are small to download, and so they load w/o a pause.
+
+      2. make sure your shaders are zippy.  
+          -avoid 'if' statements.
+          -avoid "massive zoom-outs" of any texture.  Sampling textures at too
+            high a frequency thrashes your texture cache and will drop your 
+            framerate like mad.  Sample things near 1:1, or feel free to zoom
+            in close on them, but avoid extreme zoom-outs.
+          -avoid sin() and cos() functions if you can.  If their inputs don't
+            vary from pixel to pixel, calculate the sin/cos values in
+            the per-frame equations, then store them in q1-q32, and read
+            them into your shader from there.
+          -any calculation that results in the same value for all pixels 
+            on the screen should be offloaded into MilkDrop's per-frame 
+            equations, then passed to the shader via the q1-q32 variables.
+            These variables are directly accessible from all shaders (q1,
+            q2, etc.) and can also be read in as float4's for convenience
+            (q1-q4 make up a float4 called _qa; q5-q8 come together in _qb;
+            etc.).
+          -also avoid doing motion/warping calculations in the warp shader,
+            that you could do in the per-vertex equations.  Those run on the
+            CPU, which is a huge resource that is almost never completely
+            used; the GPU, although processing 1,000 times as much math
+            because it works per-pixel instead of per-vertex, can use as
+            much of a break as it can get.  Any low-frequency effects (values 
+            that vary slowly over the screen) should go in the per-vertex
+            equations, and only the high-frequency component of the motion
+            or warping should come from the pixel shader.
+          -keep in mind that the DirectX shader compiler is superb at 
+            optimizing; anything that can be thrown out, will be.  Things like 
+               ret *= 1.0;
+               ret += 0;
+               ret += tex2D(mytex, uv).xyz * 0;
+            will completely disappear.  If you sample a texture and then the
+            sample doesn't end up making it into the final output color value,
+            the texture will never even get bound (or loaded from disk), 
+            let alone sampled.  And so on.
+          -you can use the 'half' type wherever you don't need full 'float' 
+            precision.  Generally use 'float' for UVs and time values, and 
+            'half' for almost everything else.  However, don't stress about it 
+            too much, because most GPUs run
+            everything at full-precision & full-speed nowadays - and for the
+            older GPUs that don't, the driver is probably very smart (if it's
+            an Nvidia or ATI card) about auto-substituting halfs for floats
+            wherever possible.            
+
+      3. before sharing your presets, please make sure they look good in a 
+          SQUARE or WIDESCREEN window.  If they don't, scan these guidelines
+          and you will probably be able to easily fix it.
+          
+          The overall design goal in MilkDrop, concerning aspect ratio, is to 
+          fit the preset to the long axis of the window, and to crop the rest, 
+          but to do all of this without any stretching or zooming (so all internal 
+          canvas pixels map 1:1 to screen pixels).  
+          
+          -per-frame/per-vertex equations: 
+            * multiply XY coords by the values "aspectx" and "aspecty", respectively.
+          
+          -shader code: 
+            * multiply UV coordinates by 'aspect.xy', prior to using them
+            to sample a texture, to make the texture fit on the screen properly.
+            (For example, if the screen is wide, the image will be fitted to cover
+            the width of the screen, and it will be cropped at the top and bottom.)
+            
+            * multiply by 'aspect.zw' to make it fit the other way (it will fit
+            the image to be completely visible in one dimension, and tiled in the
+            other direction).	 
+            
+            * any time you perturb the UV coordinates in the warp shader, prior to
+            sampling the Main texture, you should multiply the "delta" you are applying
+            by aspect.xy.  Otherwise, in a widescreen window, the "delta" will actually
+            be dramatically squished, or in a tall window, the change would be 
+            elongated very vertically.  
+
+        	  * the 'ang' value is aspect-aware, in the per-vertex equations, as well
+        	  as in the warp and composite shaders.  However, if you generate your own
+        	  high-quality "ang" value using atan2(), beware - you really
+        	  should multiply the UV's by aspect.xy beforehand, like this:
+                float2 uv2 = (uv-0.5)*aspect.xy;
+                float ang = atan2(uv2.y,uv2.x);
+
+        	  
+
+    
+   
+    
+    g. QUALITY ASSURANCE
+    ----------------------
+    When designing presets, please adhere to the pixel shader 'quality assurance'
+    guidelines in the above section, as they are very important.  But, in order 
+    to make sure the presets you create work well on other systems, please
+    also keep in mind:
+        
+         1. 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-vertex code that
+        are the same for every pixel; move these into the per-frame code,
+        and carry the results to the per-vertex code using the q1-q32 variables.
+        Remember that maxim: "If a per-vertex 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. Design your presets using the default mesh size 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. 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
+        (in the per-vertex equations).  Some of the best presets are 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'.
+
+         5. if writing shaders, please also see the 'Quality Assurance for
+        Shaders' section above.
+
+
+    
+    h. DEBUGGING
+    -----------------------  
+    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-vertex equations.  
+
+
+
+    
+    i. FUNCTION REFERENCE
+    -----------------------  
+    Following is a list of the functions supported by the expression evaluator
+    (for preset init, per-frame, and per-vertex equations; NOT for pixel shaders).
+    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            
+            
+
+
+
+return to top
+return to milkdrop.html
+
+ + \ No newline at end of file diff --git a/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/q_vars.gif b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/q_vars.gif new file mode 100644 index 0000000..95d0f9b Binary files /dev/null and b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/q_vars.gif differ diff --git a/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/t_vars.gif b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/t_vars.gif new file mode 100644 index 0000000..f2d3f15 Binary files /dev/null and b/musikcube_win32_with_milkdrop2_0.98.1/plugins/Milkdrop2/docs/t_vars.gif differ -- cgit v1.2.3