end ` home
Руководство по созданию пресетов MilkDrop
MILKDROP preset authoring guide
per-frame code .. покадровый
per-vertex code ..
повершинный
pixel shader .. пиксельный шейдер
warp shader .. шейдер искривления
composite
shader .. композитный шейдер
error diffusion dithering ..
сглаживание посредством диффузии ошибки
wrap mode .. режим
переноса
clamp mode .. режим фиксации
bilinear
filtering .. билинейная фильтрация
filtering and wrap .. фильтрация и
обертка
clamping .. фиксация
sampling ..
дискретизация
point sampling .. точечная
дискретизация
float и half .. числа с плавающей запятой и числа
половинной точности
* * *
Обратите внимание, что есть и другое, довольно развернутое, руководство
Preset Authoring Guide, доступное в Интернете по адресу
http://www.milkdrop.co.uk/, которое
постоянно обновляется и расширяется за счет тяжелого труда немногих посвященных
авторов пресетов. В то время как это руководство (то, который вы в данный момент
просматриваете) дает голые технические характеристики для написания собственных
пресетов, руководство milkdrop.co.uk "Для начинающих" проведет вас через все
математикие тонкости создания пресетов "добавить собственные", объясняя вещи в
мельчайших подробностях. Руководство milkdrop.co.uk очень рекомендуется для тех,
кто хочет узнать больше о создании собственных пресетов.
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. О пресетах
-----------------------
1.
About Presets
-----------------------
Когда вы видите Milkdrop, то видите серию пресетов. Каждый из них имеет
свой собственный внешний вид, собственный способ рисовать звуковые волны, и
имеет определенные последовательности движения к этому. После некоторого
промежутка времени вы увидите короткий переход через смешивание, а затем увидите
новый пресет.
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.
Единичный "пресет" является набором параметров, которые говорят Milkdrop
как рисовать волну, как деформировать изображение вокруг, и так далее. Milkdrop
поставляется с более чем 100 встроенными пресетами, каждый из которых имеет
отдельный вид и ощущение его.
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.
Используя встроенное в Milkdrop "меню
предустановки для редактирования" (ключ M), вы можете редактировать пресеты на
лету, на экране, в рамках программы. Вы можете внести небольшие коррективы в
существующие пресеты, а затем сохранить поверх существующих; или вы можете
изменить много позиций, когда пресет уже не будет выглядеть как оригинал, а
затем сохранить его под новым именем. Вы даже можете вписать новые безумные
математические уравнения, из вашего собственного воображения, в ваш файл пресета
и придумать то, чего Milkdrop никогда не делал раньше!
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!
Каждый пресет (предустановка) сохраняется в виде файла с расширением
".milk", так что вы можете легко отправить его своим друзьям или разместить в
Интернете. Вы также можете перейти на
http://www.nullsoft.com/free/milkdrop,
а затем перейти в "форум обмена пресетами", чтобы увидеть, что придумали другие
люди, или разместить свой собственный пресет, другие новые пресеты.
milkdrop.co.uk всё еще является одним большим местом, где вы можете загрузить
коллекции пресетов сделанных другими, также как и лично вами.
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. Разработка пресета - Основы
-----------------------
2. Preset Authoring - Basic
-----------------------
Вы можете редактировать свойства текущего пресета, нажав 'M', которая
вызывает "меню редактирования". Из этого меню можно использовать клавиши со
стрелками вверх и вниз для выбора пункта меню. Нажмите клавишу со стрелкой
вправо, чтобы двигаться вперед через меню и выберите элемент (замечание: вы
также можете нажать Пробел или RETURN, чтобы сделать это);
*** Нажмите левую
клавишу со стрелкой, чтобы вернуться к предыдущему меню. ***
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.***
Нажмите 'M' в то время как меню уже видимо, и это скроет меню; нажатие
ESCAPE будет делать то же самое. Нажмите 'M' еще раз, чтобы вернуться к меню
снова.
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.
Как только вы достигли пункта в меню, значение которого может быть
отредактировано, используйте клавиши со стрелками ВВЕРХ-UP и ВНИЗ-DOWN, чтобы
увеличить или уменьшить его значение, соответственно. Изменения будут немедленно
зафиксированы. Используйте PAGE UP и PAGE DOWN, чтобы увеличить значение более
быстро. Удерживайте SHIFT и с помощью клавиш UP/DOWN, чтобы изменить значение
очень медленно. Нажмите RETURN для сохранения нового значения или ESC для отмены
изменений.
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.
Если пункт, который вы редактируете является текстовой строкой, вы можете
использовать клавиши со стрелками для перемещения. Клавиша Insert может быть
использована для переключения между режимами вставки и замени символов. Вы
можете держать SHIFT и использовать клавиши со стрелками (Home, End, влево,
вправо), чтобы сделать выбор, который будет определен скобками []. Вы
можете использовать CTRL-C или CTRL-X, чтобы скопировать или вырезать текст.
CTRL-P для вставки. После завершения редактирования, нажмите RETURN, чтобы
сохранить новую строку, или ESC для отмены изменений.
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.
Вы должны привыкнуть использовать SCROLL LOCK, когда делаете изменения в
пресете, который вы собираетесь сохранить; в противном случае, с течением
времени, Milkdrop обязательно переместит вас вперед к новым (случайным)
пресетам. Когда меню отображается, установка по умолчанию автоматически временно
заблокирована, но будьте осторожны - если вы не используете SCROLL LOCK, то
через 0,1 секунды после скрытия меню, взгляните на свой новый шедевр, когда
Milkdrop может загрузить новый случайный пресет для вас, и вы потеряете все ваши
изменения! И вы тогда может быть спросите меня: "насколько большое велико". И я
скажу вам: "тридцать".
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) **
** Эти клавиши имеют эффект только если вы работаете с пресетами Milkdrop
1-го типа. В пресетах Milkdrop 2-го типа эти значения встроены в шейдере, так
что вам нужно идти в составной шейдер и настроить код там.
** 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. Разработка пресета - Расширенно
-----------------------
3. Preset Authoring - Advanced
-----------------------
В этом разделе описывается как использовать "покадровые 'per-frame'" и
"повершинные (поточечные) 'per-vertex'" уравнения для разработки новых
уникальных пресетов.
This section describes how to use the 'per-frame' and
'per-vertex'
equations to develop unique new
presets.
a. Покадровые УРАВНЕНИЯ
----------------------
a. PER-FRAME EQUATIONS
----------------------
Когда вы нажмаете "М", чтобы
увидеть меню предустановки для редактирования, несколько пунктов открываются
сверху. Если вы изучите подменю, то заметите, что все свойства, которые
позволяют вам делать пресет, доступны в данный момент для просмотра. Значения,
которые вы можете здесь задать (например, zoom amount, rotation amount, wave
color и т.д.), все значения статические, и это означает, что они не изменяются
во времени. Например, взять вариант «zoom amount» в подменю «motion». Если это
значение равно 1,0, - нет масштабирования. Если значение 1,01, - изображение
масштабируется на 1% в каждом кадре. Если это значение равно 1,10, - изображение
масштабируется на 10% каждый кадр. Если это значение равно 0,9, то изображение
отъезжает на 10% каждый кадр; и так далее.
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.
Тем не менее, пресеты получатся гораздо более интересными, если вы сможете
взять эти параметры (например, zoom amount) и анимировать их (сделать их
изменяющиися с течением времени). Например, если вы сможете взять "zoom amount"
и сделать его колебание (изменение) между 0,9 и 1,1 с течением времени,
изображение будет циклически увеличиваться и уменьшаться во времени.
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.
Вы можете это сделать выписав "per-frame" и "per-vertex" уравнения. Давайте
начнем с "per-frame" уравнений. Они выполняются один раз за кадр. Так что,
если вы пропишете следующие уравнение:
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);
... то сумма zoom будет колебаться
между 0,9 и 1,1 по времени. (Напомним, из классической геометрии, что sin()
возвращает значение между -1 и 1). Уравнение говорит: "взять статическое
значение zoom, а затем заменить его этим значением, плюс некоторые вариации".
Это конкретное уравнение будет колебаться (циклически) каждые 6,28 секунды,
поскольку период функции sin() составляет 6,28 (PI*2) секунд. Если вы хотите
сделать цикл каждые 2 секунды, то можете использовать:
...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);
Теперь, предположим, вы хотите,
чтобы цвет сигнала (звуковая волна), который формируется на экране, варьировался
во времени. Цвет определяется тремя значениями, по одному для каждой из основной
цветовой компоненты (красный, зеленый и синий), каждая из которых изменяется в
диапазоне от 0 до 1 (0 затемнено, 1 полная интенсивность). Вы можете
использовать что-то вроде этого:
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);
Будет любопытно попробовать (1,13,
1,23 и 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.
Также Вы можете сделать до 30 ваших собственных переменных. Например:
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);
Это обеспечило бы увеличение zoom amount когда музыка громкая, и
уменьшение, когда музыка тихая.
This would make the zoom amount increase when the music
is loud,
and decrease when the music is quiet.
ОДНАКО, пользовательские переменные не переносятся из покадровых уравнений
в повершинные уравнения; и если вы установите значение пользовательской
переменной в покадровых уравнениях, а потом попробуете прочитать его в
повершинных уравнениях, то не получите правильного значения. Вместо этого, вы
должны использовать возможности "bridge the gap (преодолеть разрыв)" с помощью
32 специальных переменных: от q1 до q32. Они только, и как правило,
используется, когда вы хотите, чтобы предвычисления некоторых пользовательских
значений в покадровых уравнениях поступили для последующего использования в
повершинные уравнения (или для использования в пиксельных шейдерах). Хороший
пример этого можно увидеть в "dynamic swirls" пресетах. Смотрите ниже для
получения дополнительной информации о q1-q32.
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. Повершинные УРАВНЕНИЯ
-----------------------
b. PER-VERTEX EQUATIONS
-----------------------
До сих пор мы обсуждали
только, как изменить параметры по времени. Что делать, если вы также хотите,
чтобы варьировать параметр, например, zoom amount, по-разному для разных мест на
экране? Например, как правило, результат использования параметра "zoom" - это
просто плоский зум. Это выглядит не очень реалистично, потому что вы не видите
никакой перспективы в зуме. Здесь было бы лучше, если бы мы могли дать
уникальную величину zoom amount для каждого пикселя на экране; тогда мы могли бы
сделать удаленные от центра пиксели более зуммироваными, что даёт объекту больше
перспективы. В командном коде мы используем повершинные уравнения, вместо
покадровых уравнений.
Код для такого повершинного уравнения прост:
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;
Где "rad" является радиусом пикселя, если бы он
был брошен в полярные координаты; с другой стороны, "rad" является отстоянием
пикселя от центра экрана. rad равен нулю в центре, и 1 на углах. Так что, если
мы запустим записанный выше код, изображение будет увеличено на 10% больше по
краям экрана, чем в центре.
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 }
Основная причина
различия между покадровыми и повершинными уравнениями проста: СКОРОСТЬ. Если у
вас есть повершинное уравнение, которое не использует x, y, rad, или ang
переменные, то нет никаких оснований для того, чтобы выполнять его повершинно;
оно может быть выполнено один раз за кадр, и результат будет тот же самый.
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:
Так, здесь формулируется принцип для записи на стене: "Если повершинное
уравнение не использует по меньшей мере одну из переменных {x, y, rad, ang}, то
оно на самом деле должно быть покадровым уравнением".
"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."
Вы можете быть удивлены, как все эти формулы могут быть вычислены для
каждого пикселя на экране, в каждом кадре, и как при этом будет обеспечиваться
высокий фреймрейт. Да, это магия хомяка. И факт то, что в действительности
обработка делается только в определенных точках на экране, а затем результат
интерполируется в пространство между точками. В панели конфигурации опция
"Размер ячейки (mesh size)" определяет, сколько есть точек (по X и Y), которые,
по крайней мере, в повершинном уравнения вычисляется на самом деле. Если вы
собьёте эту опцию, то начнёте пожирать циклы процессора довольно-таки быстро.
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. ПЕРЕМЕННЫЕ ПУЛЫ; Декларация собственных переменных; СОХРАНЕНИЕ
ВЕЛИЧИН
-----------------------
c. VARIABLE POOLS;
DECLARING YOUR OWN VARIABLES; PERSISTENCE OF VALUES
-----------------------
Объявление и использование своих собственных переменных достаточно просто -
в каком-то фрагменте кода (INIT уравнения, покадровых уравнения, и т.д.) вы
можете просто написать что-то вроде следующего:
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;
Это
создает переменную с именем "billy" и устанавливает его значение на 5,3. Затем
Вы можете свободно читать и/или изменять значение "billy" в этом разделе кода.
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.
Тем не менее, иногда желательно создать (на самом деле, инициализировать)
переменную в "INIT" уравнениях, а затем использовать и/или обновлять её в
"покадровых" уравнениях. Вы всегда можете сделать это, потому что в паре init и
per-frame уравнений один и тот же пул переменных. Кроме того, значения заданных
пользователем переменных будут сохраняться от кадра к кадру.
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.
Есть три "пула" переменных в Milkdrop:
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.
Как уже говорилось, хотя вы не можете прочитать значение billy в другом
пуле переменных (это сделано специально, и позволяет Milkdrop работать
качественно и быстро). Если вы хотите передать значения между разными пулами
переменных, то необходимо использовать набор специальных переменных: q1, q2, q3,
и т.д. до q32. Смотрите следующий раздел для получения подробной информации о
том, как они работают и как правильно их использовать. Просто помните: Q
переменные (и позже, Т переменные) являются единственными, которые вы можете
использовать, чтобы "перепрыгнуть" между пулами переменных (перенести значения
между ними).
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
Для этих двух секций кода, постоянные значения не имеют смысла, потому что
нет никакого способа, чтобы правильно их инициализировать. Любые
пользовательские переменные в этих участках кода должны рассматриваться просто
как временные переменные, не сохраняющиеся от кадра к кадру, от вершины к
вершине, или от точки к точке (хотя технически, они будут..., но это
вероятно, не будет то, что вы хотите). Единственное, что действительно имеет
смысл здесь, если вы хотите, чтобы перенести значения от точки к точке, когда вы
выполняете пользовательский wave per-point код; чтобы сделать это, используйте
q1-q32. (См. следующий раздел для более подробного
объяснения.)
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. Предустановленный INIT код; Перенос значений между пулами
переменных, используя q1-q32
-----------------------
d. PRESET INIT CODE; CARRYING VALUES BETWEEN VARIABLE POOLS, USING
q1-q32
-----------------------
Как мы только что видели, вы не можете нормально передавать значения между
пулами переменных. Тем не менее, есть один механизм для преодоления этого
разрыва: 'Q' переменные. Они названы q1, q2, q3, и так далее, до 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.
В Milkdrop 1.03 и старше, вы можете написать код, который будет выполняться
только один раз, когда пресет загружается (переключается на). Этот код
"инициализации пресета" делает две полезные вещи:
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. Это позволяет установить начальные значения ваших
собственных (определяемых пользователем) переменных (таких как "my_variable"),
как это было объяснено ранее.
1. It allows you to set the initial value of
your own (user-defined)
variables (such as 'my_variable'), as just explained.
2. Это позволяет вам писать по умолчанию ("sticky")
значения для q1, q2, q3... до q32. Независимо от этих значений, в конечном
итоге, после кода инициализации, те значения, которые в q1-q32 будут сброшены в
начале каждого кадра (...вход в покадровые уравнения). Если покадровые уравнения
изменяют значения q1-q32, то новые значения будут распространяются на другие
пулы переменных (см. диаграмму ниже), но к следующему кадру значения будут
сброшены к оригиналу "sticky" по умолчанию.
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.
См. ниже на блок-схему, где представлены краткий и более полный взгляд на
то, как значения из Q переменных проходят через Milkdrop.
See the flow chart below for a brief, and complete,
glance at how the values
of the Q variables flow
throughout MilkDrop.
http://www.cmana.net/MEDIA/Winamp/Plugins/Milkdrop2/docs/q_vars.gif\
qi
... q32 variables - flow of values:
\
CUST. WAVE PER-FRAME
point
0
CUST. WAVE PER-POINT*
points 1+
\
PRESET INIT. CODE
§
PRESET
PER-FRAME
PRESET PER-VERTEX
\
CUST. SHAPE PER-FRAME
WARP
SHADER
COMPOSITE SHADER
\
§ ... the initialization code is only
executed once, when the preset is loaded. For every frame after that, the values
of q1...q32 that came from the original mit code are what get passed on.
Давайте проследуем через этот поток на
графике.
Let's walk through the flow of the chart.
Если вы прописываете значения q1..q32 из
"preset init code", эти значения становятся новой "базовой величиной", для
которой q1..q32 инициализируются в начале каждого кадра, для каждого покадрового
кода. Поэтому, когда вы получаете доступ (считываете) q1-q32 в покадровом коде,
вы получите значения, которые были *первоначальной* установкой - снова и снова,
каждый кадр. Вы можете изменить их (или нет) в каждом покадровом коде, и
(возможно изменить значения) они будут читаться в повершинном коде - а также как
и во всех pixel shader кодах, и также как и во всех других. Тем не менее, все
измененные значения не будут сохраняться в следующем кадре; они будут снова
сбрасываться в начале следующего кадра к значениям, которые они имели в конце
preset init кода.
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.
В повершинном коде, начальные значения q1-q32 (для первой вершины в каждом
фрейме) есть значения, которые они имели в конце покадрового кода. Если вы
измените q1-q32 в повершинном коде, эти измененные значения будут перенесены от
вершины к вершине (Это не очень желательный эффект; вы должны избегать записи в
Q переменные из повершинных уравнений). В следующем кадре они будут сброшены на
необходимое значение, которое они имели в конце [в следующем кадре выполнения]
покадрового кода. (Это все есть в схеме... посмотрите на неё, и вы сможете
просто получить его.)
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.)
Здесь существует одна хитрость. Вы могли заметить, что пользовательские
wave/shape init боксы отсутствуют в схеме. Это потому, что Q переменные,
выходящие из них, никуда не идут. Значения Q, которые приходят в покадровые
wave/shape уравнения приходят из покадрового уравнения пресета, как вы можете
видеть. Но, просто вам ради юмора: в wave/shape init коде, значения Q поступают
в результат из preset init кода. Любые значения Q, которые вы пишете там (в
wave/shape init коде) не будут иметь смысла; хотя вы и можете написать
(инициализировать) ваши собственных пользовательские переменные, и прочитать их
позже, в wave/shape покадровых уравнениях! Так, на самом деле, вы все равно
можете маршрутизировать данные таким образом, если вы действительно этого
хотите.
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.
Примечание: когда вы редактируете preset init код и применяете его (нажав
CTRL+ENTER), код инициализации сразу переоформляется. Однако, когда вы
редактируете регулярный покадровый/повершинный код и нажмимаете CTRL+ENTER,
заданный Init код пресета не будет выполнен повторно; и при этом сохранятся
результаты последнего выполнения. Если вы измените покадровый/повершинный код и
захотите повторно выполнить инициализацию кода (т.е. рандомизировать его
случайным образом или сбросить пресет), то вам придётся сохранить пресет, а
затем повторно загрузить его.
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.
(Историческая справка: здесь ничего не изменялось начиная с Milkdrop 1; эти
диаграммы были просто повторно переработаны, чтобы стать много проще для чтения.
Но, на самом деле, в старых схемах была ошибка, которая в настоящее время
исправлена: на фрейме 0, они показывали значения Q поступающие прямо из (кадр
0!?) покадрового кода, в пользовательском волны/формы кода инициализации. На
кадре 0, эти значения Q, на самом же деле, поступают прямо из кода инициализации
пресета. Однако, они практически бесполезны, как было описано выше.)
(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
----------------------
По состоянию версии Milkdrop 1.04, доступны две новых функции:
Пользовательские формы, а также Пользовательские волны. Пресет может иметь до
4-х каждой из них.
As of MilkDrop 1.04, two new features are available:
custom shapes, and custom
waves. A preset can have
up to 4 of each.
С пользовательскими формами, вы можете нарисовать n-стороннюю форму (с
3-100 сторонами) в любом месте на экране, под любым углом и любого размера, в
любом цвете, и с любой степенью непрозрачности. Вы даже можете получить
возможность зафиксировать изображение предыдущего фрейма в форму, которую можно
будет использовать для получения некоторых невероятных возможностей (таких как
аппаратные фракталы в режиме реального времени - см. пресет "Geiss - Feedback").
Вы также можете написать покадровый код, чтобы контролировать все эти вещи
относительно формы(форм). Таким образом, они могут реагировать на аудио или
изменяться с течением времени - то есть, делать всё то, что только вы можете
себе представить. Вы ограничены четырьмя пользовательскими формами для каждого
пресета, однако, каждая из них может быть опорой (instanced), который позволяет
рисовать огромное количество (до 1024) из них на каждый кадр, если вы захотите,
и каждый из них может быть совершенно другим (до тех пор, пока значение
"опорной" instance-переменной не закончит влияние на другие свойства).
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).
С пользовательскими волнами, вы можете нарисовать волновую форму (или
спектр частот) где угодно, когда угодно, и как угодно вы хотите; это есть
существенное дополнение к Milkdrop 1.03, где были возможны только встроенные
волновые формы. С пользовательскими волнами вы также можете написать покадровый
код для контроля волн, и разместить поточечный код для каждой точки (или для
отрезка прямой) на волне, где именно вы хотите, с заданным цветом, который вы
захотите, и так далее.
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.
Помните те переменные q1-q32, которые помещаются в конце кода инициализации
пресета, затем сбрасываются (к исходным значениям) в начале каждого кадра, а
затем (возможно) могут быть изменены в покадровом коде пресета? Те (потенциально
изменяемые) значения q1-q32 - как они были в конце покадрового кода пресета, в
каждом кадре - будут направлены по конвейеру в пользовательский wave и
пользовательский shape покадровый код. Так что, если вы читаете q3 в
пользовательском wave покадровом коде, то вы действительно читаете значение q3,
как он был оставлен под конец в покадровом коде этого кадра. Опять же,
посмотрите на изображение q_vars.gif где представлена диаграмма потока значений
переменных q1-q32.
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.
Для пользовательских волн и форм, вы можете изменять q1-q32, если хотите, в
покадровых уравнения. Как обычно, значения Q переменных не сохраняются от кадра
к кадру, хотя - они будут сброшены на каждом новом кадре, в соответствии с
значениями, которые они имели в конце покадрового кода *пресета*, этого кадра.
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.
Для пользовательских волн, вы также имеете еще одно звено в цепи:
поточечный (также известный под именем повершинный) код. Этот код выполняется
один раз для каждой точки данных в сигнале. Поступающие начальные значения
q1-q32 (для первой точки) являются величинами, которые стояли в конце
пользовательского волнового покадрового кода, этого кадра. Если вы измените
q1-q32 в поточечном коде (или даже если вы не будете этого делать), то значения
перейдут к следующей точке. Вы могли бы, например, сгладить сигнал, используя
это.
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.
Переменные 'T'
----------------------
THE 'T'
VARIABLES
----------------------
Есть 8 дополнительных переменных, доступных для пользовательских волн и
форм: t1-t8. Они очень похожи на Q переменные, но они существуют только для
пользовательских волн и форм. Чтобы увидеть, как потоки данных из пула
переменных перетекают к пулу переменных для переменных Т, взгляните на рисунок
ниже. Так Q переменные существуют, чтобы помочь вам преодолеть отставание пула
переменных. Тем не менее, T переменные немного проще для понимания, чем Q.
Диаграмма ниже должна объяснить все это.
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.
http://www.cmana.net/MEDIA/Winamp/Plugins/Milkdrop2/docs/t_vars.gif\
ti
... t8 variables - flow of values:
\
CUSTOM WAVE INIT.
§
CUST. WAVE
PER-FRAME
point 0
CUST. WAVE PER-POINT*
points 1+
\
CUSTOM SHAPE
INIT.
§
CUST. SHAPE PER-FRAME
\
§ ... the mit code for custom
waves/shapes are only executed once, when the preset is loaded. For every
frame
after that, the values of t1...t8 that came from the original mit code
are what get passed on.
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
----------------------
Мир компьютерной графики создаваемой в реальном времени, сделал огромный
шаг с 2002-2003, именно при появлении пиксельных шейдеров. Много людей хотят
узнать, как использовать пиксельные шейдеры; и написание пресетов для Milkdrop
является прекрасным способом узнать их, потому что вы сможете увидеть эффект от
вашего кода мгновенно, непосредственно на экране.
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
стоял на том, что называется "фиксированной функции" графический конвейер. Это
означало, что некоторые наиболее часто встречающиеся графические операции - и
очень немногие из них - могут быть выполнены для каждого пикселя. Вы могли бы
делать несколько вещей - может быть преобразовать текстуру или цвет, затем,
возможно, произвести еще одну простую операцию - но это было именно об
этом.
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.
Новые пресеты (Milkdrop 2 и выше) уже могут использовать программируемые
пиксельные шейдеры. ЦПУ (устройства графического процессинга) в настоящее время
способны выполнять десятки и даже тысячи (на более дорогом оборудовании)
инструкций на пиксель. Чтобы сообщить ЦПУ, что делать в каждом пикселе, вы
пишете код, который называется "пиксельный шейдер". Это выглядит очень похоже на
язык программирования C, за исключением того вы ещё увидите типы float3
(...часто представляющие цвет, или, может быть, 3D координату), также как float2
и float4, и так часто, как вы будете видеть простой "float" тип. Также, много
внимания отводится отбору текстур. Текстуры могут быть либо процедурные (как на
изображении из предыдущего фрейма, или красиво гауссово-размытых его версиях,
или как на процедурно-генерируемого шумовых текстурах), или они могут быть
загружены с диска. Для отбора из текстуры на диске (...но, конечно, которые
кэшируются в видеопамяти), в шейдер, просто укажите имя файла с изображением,
которое вы хотите загрузить, и укажите как вы хотите пробовать его (какой вид
фильтрации и обертки), а также где хотите пробовать (UV координаты, как и XY
координаты, всегда в диапазоне [0..1]). Он считывает образец (как float4 -
поскольку некоторые графические форматы имеют четыре канала, а не только R/G/B).
Вы можете (математически) делать с этим образцом все, что вам нравится, в том
числе принимать другие образцы, объединять их, и так далее. Окончательный вывод
шейдера всегда является значением цвета, и это именно то значение цвета, которое
записывается в результирующий рендер (как внутренняя текстура, или как то, что
есть на экране).
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).
ШЕЙДЕР модели - 2.0, 3.0 и т.д.
------------------------------
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 поддерживает только графику с
фиксированными функциями - т.е. не поддерживает пиксельные шейдеры.
Milkdrop
2 поддерживает Shader Model 2 на самом низком уровне. (Если ваш GPU не
поддерживает этого, Milkdrop 2 все равно должен работать - поэтому он просто не
будет показывать вам те пресеты, которые используют пиксельные шейдеры.) Хотя,
Shader Model 2 имеет ограничение 64 инструкциями (на один шейдер).
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.
Помимо этого, пресеты могут быть авторизированы и для использования Shader
Model 3. Эта шейдерная модель поддерживается ещё не так широко (... так что
будьте осторожны в написании пресетов для неё - так как половина чипов пока не
поддерживают её, и эти пресеты не будут отображаться в списке пресетов на таких
компьютерах). Тем не менее, это гораздо более мощный инструмент, с практически
неограниченным числом команд. (Вы ограничены только скоростью вашего GPU, и
количеством пикселей, которые вы должны прорисовывать каждый кадр!) На GeForce
8000-й серии, можете верить или нет, вы легко можете достигнуть плавной смены
кадров, при работе шейдеров с ТЫСЯЧЕЙ инструкций!
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 так же существует, но только в DirectX 10; а DirectX 10
доступен только в Windows Vista. Покуда не так много людей используют Vista, то
мы решили не ждать (чертовски долго), пока будет пройден этот долгий путь. В
любом случае, Shader Model 3 имеет в себе практически все, что
нужно.
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
------------------------------------
Обратите внимание, что если вы загружаете Milkdrop 1 пресет, то можете
сохранить его обратно на диск (даже после изменения кода, переменных и т.д.), и
он будет по-прежнему читаемым посредством Milkdrop 1. Только если вы выберете
пункт меню [его] "Upgrade Pixel Shader Version", то вы далее сделаете его не
обратно-совместимым. Хотя, после того, как вы сделали это, вы заметите, что меню
теперь будет выглядеть немного иначе - могут появиться некоторые новые настройки
на основе шейдеров, а некоторые старые пункты (видео эхо, гамма и т.д. - все
вещи, которые в настоящее время собраны в композитный шейдер), все они пропадут.
Вы также заметите, что появились два новых шейдера по умолчанию (warp и
composite), которые были написаны для вас, и соответствующие значения и
параметры из старых пресетов (gamma, decay, video echo, texture wrap и т.д.),
все настроены корректно в новых шейдерах, поэтому пресет делает всё то, что и
делал раньше. Единственной разницей является то, что сейчас пресет пользуется
полной программируемостью пиксельных шейдеров (и у вас есть много свободы для
его настройки), вместо ограничений весьма ограниченной DX8 с фиксированными
функциями графических конвейеров.
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.
Некоторые
из объема функций (обсуждаемых ниже) будут смешивать старые и новые пресеты
вместе. В этом случае, вновь созданный пресет-файл будет правильно выглядеть
только на Milkdrop 1.xx, если он не использует ни искажение (warp), ни
композитный шейдер (composite shader). Он по-прежнему будет работать в Milkdrop
1, но без шейдеров, поэтому все, random values gamma, video echo, и т.д. [were
left at, will all kick back in].
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.
И последнее замечание: имейте в виду, что Milkdrop 2 достаточно умен, чтобы
не показать вам какие-то пресеты, которые ваш ЦПУ не может поддержать. Milkdrop
1, однако, не такой умный - и это позволит вам видеть Milkdrop 2 пресеты. Хотя,
вероятно, Milkdrop 1 будет игнорировать всё шейдерное содержимое, и отображаться
пресеты будут неправильно.
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
-------------------------------------
Игры произвели настоящую аппаратную графическую революцию, и теперь игры
работают, проецируя тысячи 3D треугольников на экране, растрируя (раскладывая
изображения на элементы) и затеняя их. В Milkdrop, кроме этого, блок
графического процессора (ЦПУ) также дает задание создавать большое количество
треугольников на экране. Каждый треугольник описывается тремя вершинами
(точками). Интерьер треугольника является связкой пикселей. ЦПУ выполняет ваш
"шейдерный" код в каждом пикселе, чтобы определить, какой оттенок будет иметь
пиксель - то есть, его яркость, или определение его цвета. (Терминология большей
степени ориентирована на идею, что эти треугольники были изначально в 3D и
требовали реалистичного освещения и затенения.)
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.)
В Milkdrop, шейдеры работают на статичной, регулярной сетке треугольников,
которая охватывает все видимое окно. Результаты настройки повершинных уравнений
пресетов интерполируются через поверхность каждого из этих треугольников, и ваш
пиксельный шейдер будет видеть интерполируемые результаты. Они приходят в виде
"UV" координат - и они говорят вам, где брать (читать) исходное изображение,
чтобы создать нужный эффект деформации каждого кадра - долгосрочным эффектом
которого является создание визуально воспринимаемого движения.
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.
Вы можете попробовать использовать данное изображение (или другие),
наложить некоторую математику на результатирующее изображение, попробовать
некоторые другие текстуры, сделать некоторую дополнительную математику, и т.д. К
концу шейдера, любое значение в "ret" (float3 - это трехзначное величина с
плавающей точкой) является цветом, который будет прописан для этого
пикселя.
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.
Каждый пресет в Milkdrop 2 имеет два пиксельных шейдера: шейдер
искривления, который искажает изображение от кадра к кадру, и шейдер
композитный, который рисует рамку на экране (с или без спецэффектов).
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).
Чтобы изменить или поэкспериментировать с этими шейдерами, когда Milkdrop
работает, нажмите "M" для просмотра меню редактирования пресетов. Прокрутите
вниз к следующему
[редактировать шейдер
искривления]
или
[редактировать композитный
шейдер]
и нажмите ENTER. Если вы не видите ни один из этих вариантов, то это
означает, что текущий пресет сделан как старый Milkdrop 1 пресет; в этом случае,
вы можете либо попробовать другой пресет, или вы обновить текущий пресет, выбрав
[обновить версию пиксельного шейдера пресета]
в нижней части
меню. Имейте в виду, что если вы обновляете версию пиксельных шейдеров пресета,
а затем сохраняете его на диск, то он может быть больше непригоден для
использования на других компьютерах со старыми чипами.
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.
Теперь перейдите к редактированию одного из этих двух шейдеров. После того,
как вы окажетесь там в режиме редактирования, нажмите клавишу F9 - она будет
переключать на экране быструю ссылку для записи шейдеров. Это очень удобно.
Нажмите клавишу F9 ещё раз, чтобы скрыть ссылку.
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;
}
Есть только две команды здесь... выбрать старые фреймы, и затемнить старое
значение цвета (значения цвета всегда находятся в диапазоне 0..1), чтобы с
течением времени не допустить переход экрана в белый цвет.
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.
Этот код выполняется в каждом пикселе на экране. Если бы UV входили в
диапазон [0..1] на осях X и Y, точно в соответствии с расположением пикселей на
экране, то не было бы никакого движения (или искривления). Что создает перекос в
том, что UV-координаты несколько "выключены". Каждый кадр, Milkdrop выполняет
повершинные уравнения для текущего пресета во всех вершинах на сетке,
покрывающей экран. Полученные UV координаты интерполируются (посредством ЦПУ)
между вершинами, и этот шейдерный код выполняется в каждом пикселе, с UV
координатами, которые гладко интерполируются для вас, чтобы сделать вашу
выборку. Следует отметить, что оригинальные, неискаженные UV координаты всегда
доступны в uv_orig. Если пресет не произвел никакого изменения в нем, или, если
бы мы использовали uv_orig вместо uv, то мы просто увидели бы как пиксели
темнеют со временем, без видимого движения.
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.
Обратите внимание, что внутренний холст Milkdrop (текстуры) может хранить
цвета только в диапазоне [0..1], так что, если ваши шейдерные значения выходят
за пределы этого диапазона, то они будут обрезаны до 0 или 1. В теле шейдера, вы
можете сойти с ума, используя различное количество областей по своему желанию;
но это ограничение относится только к конечному выходу.
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.
Обратите внимание, что есть несколько способов затемнить пиксели с течением
времени, и точный цвет (8 бит на цветовой канал, или 256 оттенков, или [0..1] с
шагом 0,004) означает, что вы должны быть осторожны с потемнением цвета с
течением времени. Если же вы собираетесь затемнить пиксели, воспользуйтесь этим
выражением:
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;
причем вы не должны использовать мультипликатор выше 0,98, потому что, по
причине точности исчисления, затемненные пиксели никогда не станут совсем
темными. Еще один способ сделать подобное, использовать выражение:
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;
}
Композитные шейдеры понять легко. Мы можем просто попробовать поместить
внутренний холст на UV координаты (здесь возможны искажения, но мы можем
поэкспериментировать с ними если захотим!), и манипулировать результатом при
желании (здесь мы украсим результат еще немного). "Пересвечивание" здесь
благоприятно, потому что пиксели в диапазоне яркости (только в представлении
пользователю) вымываются в белый цвет; однако, они могут оставаться такими
недолго. Если мы просто отображаем цвет как есть, и избегаем рисования наших
сигналов с удвоенной яркостью, то они, скорее всего, будут начинать с белого
цвета, но очень быстро будут исчезать в оттенки серого.
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));
Это перевернет изображение вокруг его
диагонали, всегда показывая вам более яркие пиксели из двух ориентаций, а затем
нарастит R/G/B каналы на различные показатели для создания немного серого
оттенка. Не слишком жестко!
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
------------
Если вы знакомы с C/C++, вы можете использовать простые вещи,
как
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
----------------------
Если не указано иное, эти инструкции всегда работают с float, float2,
float3, или float4 операндами.
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
{
...
}
Имейте в виду, что cos(), sin(), и atan2() являются невероятно
медленными (~8 инструкций). Почти все остальное (даже деление, извлечение
обратного квадратного корня и т.д.) составляют одну или, может быть, самое
большее, две инструкции.
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.
Следует
отметить, что команда saturate(), а также умножение на 2, 4, или 8, или деления
на 2, 4 или 8, являются базовой операцией на многих ЦПУ. И арифметико-логическое
устройство (АЛУ) внутри GPU почти всегда делают умножение и сложение (оба
одновременно) в одной инструкции.
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.
Кроме того, вы можете разделить его на целую константу без суффиксации с
".0"; В C/C++, "float х = 1/5;" даст вам НОЛЬ; но на языке шейдеров, это
даст вам то, что вы ожидаете: 0.2.
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).
Заметим, что для обоих шейдеров, значение
угла при вершине, с интерполяцией (ang), становится немного ненадежным в центре
экрана, где очень трудно производить качественную интерполяцию (потому что она
неожиданно не помещается в диапазон от 0 до PI*2 в 9 часов на вашем экран). Если
вы видите артефакты из-за этого, просто используйте
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);
Значения неискаженных UV значений всегда будет безупречного
качества, хотя бы потому, что они будут интерполированы в направлении, в котором
они изменяются, а прямолинейная сетка является идеально ровной и подходит для
этого.
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 каналы содержат много данных в шейдерах. Вот список всего, к чему
шейдеры могут получить доступ.
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
----------------
Мы уже использовали одну текстуру: внутренний холст, также называемый
"Main". Поскольку он используется всегда, то вы не должны его декларировать. Вы
можете просто использовать его. Тем не менее, у вас есть несколько вариантов для
того, как его опробовать. Есть четыре квантизатора связанных с основным
холстом:
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
* Вы также просто можете использовать "sampler_main" для этих целей,
так как это на сегодняшний день наиболее часто делается.
* you can also just use
"sampler_main" for this
one,
since it's by far
the most common.
Когда вы следуете к квантизатору текстуры, ЦПУ находит точное место в
текстуре, которое определяется UV-координатами точки. Есть большая вероятность,
что он попадает в промежуток между 4 текселями (пикселями), а не точно на один
из них. Если вы используете билинейную фильтрацию для выборки, то он вернет
средневзвешенное значение четырех пикселей. Если вы используете точечную выборку
(дискретизацию), это он просто вернет вам ближайший одиночный пиксель (также
называемый "ближайший сосед").
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 против Clamp также довольно просто: если вы укажете UV
координаты float2(-0.1, 0.5), режим переноса сопоставит их координатам (0.9,
0.5), в то время как режим фиксации закрепит их в диапазоне (0.0, 0.5). Режим
Wrap способен создавать "кафельные" изображения, в то время как режим Clamp
берет цвет на границе и расширяет его до бесконечности.
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.
В общем, другие текстуры могут быть отобраны
аналогичным образом, с помощью всё тех же двухбуквенных префиксов ("_fw", "_pc",
и т.д.). Или, вы можете не использовать префикс, и Milkdrop будет предполагать,
что вы хотите использовать "_fw" - билинейная фильтрация и режим Wrap - по
умолчанию.
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 - главная, размытие, и
шум
---------------------------------------------------
MILKDROP'S BUILT-IN TEXTURES - MAIN, BLUR, and
NOISE
----------------------------------------------------
Milkdrop имеет несколько встроенных текстур, которые можно
попробовать.
MilkDrop has several built-in textures you can sample
from.
ГЛАВНАЯ
----
MAIN
----
Во-первых, основная текстура (внутренний холст). Как уже говорилось, вы
можете опробовать её с помощью sampler_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
-------------------
BLUR1, BLUR2, BLUR3
-------------------
Далее, существует несколько версий размытия основной текстуры. Они
называются 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 возвращает слегка размытое изображение, GetBlur2 более размытое
изображение, а GetBlur3 чрезвычайно размыто изображение. Обращение к любой из
GetBlur функций происходит очень быстро, но имейте в виду, что размытые текстуры
генерируется каждый кадр, только если шейдеры на самом деле их используют, и
результаты находят свое место в конечном значении цвета выходного сигнала
пиксельных шейдеров! Если Blur1 является самым быстрым для генерирования; то
следом идёт Blur2 (так как он генеририруется из Blur1); и, наконец, Blur3
является самым медленным (генеририруется из Blur2).
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;
Эффект "точечный скин" в некоторых из
пресетов (он делает пятна и полосы, какие вы можете увидеть в природе на рыбе
или на леопардах) основывается на очень мягком обнаружении края в *warp*
шейдере, и использует его для обеспечения определенного количества дисперсии в
цветовых значениях. Он также служит для разбивки больших поверхностей, состоящих
из сплошного белого пикселя.
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.
Обратите внимание, что вы можете сделать некоторые интересные эффекты
свечения за счет повышения "min" значения выше 0. Скажем, например, вы
устанавливаете blur1_min на 0.5. Это означает, что любые пиксели с значениями
цвета ниже 0.5 будут подрезаны до 0.5. Так что, когда вы вызываете GetBlur1(),
это дает вам значения в диапазоне [0.5 .. 1.0]. Тем не менее, поскольку вы
используете только половину диапазона возможных значений, точность этих значений
будет в два раза лучше. Это является целью min/max значений. Будьте внимательны
что, хотя ваши значения обрезаются до минимума в 0.5, это будет выглядеть плохо,
если вы на самом деле имеете цвета, которые находятся выше 0.5, а вы не
вычитаете то, что выходит за границу 0.5.
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.
Тем не менее, если вы установите min, а затем вычтете его, вы также сможете
получить некоторые большие эффекты свечения, где только действительно яркие
пиксели внесут свой вклад в "свечение". Если вы установите min на 0.7, например,
а затем пропишите следующим образом:
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;
Это будет вычитать минимальный порог в 0.7, но
из-за отсечения, вы сможете увидеть в основном только яркие "светящиеся"
пиксели. Множитель *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
--------------
Также есть "шумовые" текстуры (случайная величина), встроенные в Milkdrop.
Они генерируются, когда Milkdrop запускается, однако большое количество
(случайных) данных не должны раздувать размер загружаемого файла Milkdrop. Они
отличаются по качеству (гладкости) шума, а также по частоте повторения картины.
Всегда используйте наиболее компактную доступную шумовую текстуру (_lite или _lq
версии), если это возможно.
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
Обратите внимание, что четыре из
них являются двумерными (попробуйте использовать tex2D (float2 uv)), и два из
них являются трехмерными (попробуйте использовать tex3D (float3 uvw)).
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!
Суффиксы _lq, _mq и _hq обозначают низкое, среднее или высокое качество.
Непосредственно _lq текстуры имеют одну случайную величину в каждом текселе
текстуры. А _mq текстуры имеют (как правило) около четырех текселей на одну
случайную величину, с высоким качеством [кубической] фильтрации, запечатанной в
текстуре. (Иногда вы просто хотите чего-то лучшего, чем билинейная фильтрация,
вы в курсе?) Высококачественные текстуры, как правило, имеют по 8 текселей для
каждой случайной величины. Размеры здесь даны в пикселях, но на самом деле
являются абстракциями - они концепциии # пикселей (значения) до их повторения.
На самом деле, текстуры значительно больше (для среднего и высокого качества), и
все дополнительные тексели выычисляются при помощи высококачественной
интерполяции.
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.
Более качественные текстуры не являются как-либо особо более медленными в
использовании, но при условии, что вы будете применять их с правильной частотой.
Если вы попробуете любую из текстур при слишком высокой частоте (т.е. уложите их
плиткой, как сумасшедший / или умножите их большим количеством UV координат), то
кэш памяти видео текстуры приведет ваш ЦПУ к полной остановке. Не делайте этого!
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!
При использовании шумовых текстур с настройками квантизатора по умолчанию
(фильтрация и обертка), вы не должны объявлять их перед shader_body; они всегда
объявлены и имеются в наличии. Однако, если вы хотите попробовать их
дополнительные параметры (фиксацию или точечную дискретизацию), то вы должны
сделать следующее. (Например: "квантизатор sampler_fc_noise_lq", или
"sampler_pw_noise_lq").
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 );
Это
выражение возвращает значения float4 в диапазоне [0..1]. Тем не менее, шумовое
мзображение будет растянуто так, что 64x64 пикселей покроют весь экран. Чтобы
нам это больше понравилось, нужно уложить его плиткой таким образом, чтобы карта
шумовых значений совпадала 1:1 с пикселями на экране.
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.
Чтобы сделать это, нам необходимо вызвать другую удобную функциию: вы
можете получить размер любой текстуры в Milkdrop. Просто объявите float4 (до сих
пор вне шейдера body) с именем текстуры, которому предшествует "texsize_" - как
то:
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
);
Он будет делать именно это. Что является очень распространенной
и полезной техникой. uv_orig дает вам оригинал (unwarped) UV координаты [0..1].
Если мы затем умножим его на texsize.xy, то получаем количество пикселей,
которое находимся в диапазоне. Например, если экран был 1280x1024 пикселей, то
мы получим float2 в диапазоне [0..1279, 0..1023]. Если затем мы умножим
результат на texsize_noise_lq.zw, мы разделим на размер шумовой текстуры, в
пикселях (это одна текстура 256x256). Таким образом, мы в конечном итоге придем
к UV координатам примерно в диапазоне [0..5, 0..4] - наш образ стал выглядеть на
экране как идеальная плитка, с отображением пикселей 1:1.
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.
Этот алгоритм может быть использован для того, чтобы смешать в изображении
для каждого кадра бит случайного шума, который может увеличить качество
изображения - это похоже на ошибку диффузионного сглаживания (которая является
одной из главных идей, чтобы устанавливать оригинальный Geiss плагин/заставку
отдельно от других, что очень мудро в плане качества изображения!). Вы может
задуматься почему. Кроме того, что дальше добавляет "rand_frame.xy" к UV
координатам, значения шума будет изменяться для каждого кадра, делая его,
кажется, действительно случайной [изменяющейся] шумовой величиной:
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;
Это позволит добавить много
шума в изображение на каждый кадр. Добавление "Rand_frame.xy" к UV координатам
служит для обеспечения случайного размещения шумовой текстуры для каждого кадра,
и предотвращения отпечатка шума из него, точно так же, каждый кадр, что и могло
бы привести к появлению артефактов.
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.
Важно: Обратите внимание, что в средне- и высоко-качественные текстуры не
должны использоваться для отображения 1:1! - это огромная трата вычислительных
ресурсов. Вы только тогда выиграете от их высокого качества, если вы
*зуммируете* эти текстуры, будете видеть их увеличенными, но будете
дискретизировать их на низкой частоте. Если они минимизированы (дискретизированы
на высокой частоте / с измененным масштабом) или даже представлены как 1:1, то
вы быстро переполните кэш видеопамяти и пресет будет работать очень медленно.
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
--------------------------
Декларирование и дискретизацию ваших собственных текстур сделать легко.
Во-первых, необходимо создать свою текстуру. Если вы планируете делиться своими
пресетами с другими людьми, то, пожалуйста, убедитесь, что текстура имеет
небольшой размер (256x256 или меньше) и сохраните её в виде файла в формате JPG
и с качеством 95%. Размер файла должен быть между 10k и 50k (килобайт). Конечно,
если вы хотите, текстурами могут быть огромные, четкие фотографии - но они
просто будут слишком тяжелы (для отправки другим людям) и будут вызывать
некоторую задержку, когда вы переключаетесь на пресет, который их использует (и
который соответственно загружает текстуру).
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
или там, где вы
установили Winamp и Milkdrop. Давайте представим, что вы назвали текстуру
billy.jpg.
Тогда, в любом шейдере, до раздела shader_body, небходимо заявить
сэмплер для текстуры:
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;
Вот и все, что вам нужно сделать. Он
найдет файл (billy.jpg) и загрузит его. Обратите внимание, что имя сэмплер НЕ
ДОЛЖНО начинаться с "Sampler_", и если вы хотите это сделать, то можете
использовать префикс "sampler_pc_" или "sampler_fw_" (или любой другой
подобный), для того чтобы включить фиксатор текстуры и/или точечную
дискретизацию.
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)
Теперь, когда вы объявили структуру, вы можете опробовать её в разделе
shader_body:
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;
Итак, сначала он будет
пытаться найти billy.jpg; затем billy.dds; и так далее, пока не найдет
правильную текстуру. Если текстура не может быть найдена в директории
"milkdrop2\textures", то он еще попробует найти её **в текущем каталоге
пресетов**; Это делается для того, что загрузчики пресетов могут быть слишком
ленивы и могут поставлять пресеты непосредственно с текстурами, в том же
каталоге.
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.
Если ваш шейдер хочет знать, как велика текстура, то заявите об этом (также
выше раздела shader_body):
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 увидит код "texsize_", и автоматически будет знать, что нужно
делать. (Вы, конечно, не должны включать в свой код комментарий //).
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;
Или разместить плиткой так, чтобы пиксели были
представлены 1:1:
Or to tile it so the pixels
are represented 1:1:
ret = tex2D(sampler_billy, uv *
texsize.xy * texsize_billy.zw).xyz;
Или отобразить её
плиткой, множенной ровно в 5 раз:
Or to map it tiled exactly 5 times:
ret = tex2D(sampler_billy, uv *
5).xyz;
Или, чтобы увеличить в центре 20% изображения:
Or to zoom into the center 20% of the image:
ret = tex2D(sampler_billy,
(uv-0.5)*0.2 + 0.5 ).xyz;
Конечно, вы можете также объявить
sampler_pw_billy, чтобы сделать дискретизацию точки, или sampler_fc_billy, для
фиксации, и так далее.
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
------------------------
Вы также можете загрузить случайную текстуру. Просто используйте название
"rand00" по "rand15", как имя файла, и Milkdrop сам подберет случайный файл и
сделает все остальное. Параметры texsize_ тоже работают. Например:
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);
...
}
Также вы
можете выбрать из подмножества случайных текстур на диске! Скажите, что у вас
есть целая куча случайных текстур в подкаталоге textures\, но у вас есть
подмножество и там, где названия начинаются со слова "smalltiled".
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);
...
}
Тогда, каждый
раз, когда пресет загружается (или перекомпилируется шейдер), будет
производиться выбор новой случайной текстуры, но это будет выбор только из
подмножество тех текстур, чьи названия начинаются с "smalltiled".
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".
Одна последняя вещь, полезный совет: если вы работаете в оконном режиме
(или в режиме мультимонитора), и добавили текстуры в каталог, но еще не вышли из
плагина, чтобы форсировать обновление списка текстур, измените один из шейдеров
(любой шейдер), а затем нажмите CTRL+ENTER (принять). Это вызовет обновление
списка файлов (но делайте так только когда это необходимо, потому как ваш шейдер
запросит новую случайную текстуру).
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 была полезная
функция "затемнение центра", которая быстро гасила яркие пикселы, расположенные
в центре экрана, потому что в "масштабирующихся" (движущихся вперед) пресетах,
экран быстро становится полностью белым, если вы этого не сделали. Так пресеты
получались более изощренными, хотя, где находится "центр" движения
масштабирования, может быть очень трудно определить.
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.
В действительности вы можете найти его алгоритмически. Если где-то на
экране вы имеете UV координаты, которые очень близки к исходным UV координатам,
то это означает, что или там нет никакого движения, или что это центр движения -
при этом вы знаете какой пресета использовали. Если это пресет
"масштабирования", то, вероятно, последнее [центр движения]. В этом случае,
просто напишите что-то подобное в вашем шейдере деформации:
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
-----------------------
RANDOM DIFFUSION
DITHER
-----------------------
См. выше, в разделе «шум».
See above, in the "noise"
section.
ФУНКЦИЯ MAX
--------
SOFT MAX
--------
Функция max(a,b) возвращает максимальное значение для каждого из двух
входящих каналов, однако, это иногда может иметь весьма прерывистый вид, так как
она переключается с "a" на "b" или назад достаточно внезапно. Если же вы хотите
пусть не особо аккуратную, но всё таки более плавную функцию 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
Следует отметить, что входы должны быть в диапазоне
[0..1].
Note that the inputs must be in
the [0..1] range.
КОНТРОЛЬ КАЧЕСТВА
ШЕЙДЕРОВ
-----------------------------
QUALITY
ASSURANCE FOR SHADERS
-----------------------------
*Пожалуйста* придерживайтесь этих принципов при написании шейдеров...
*Please* adhere to these guidelines when writing
shaders...
1. используйте небольшие (256x256 или меньше) текстуры; сохраняйте их в
виде JPG 95%
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. убедитесь, что ваши шейдеры работают.
2. make sure your shaders are zippy.
- избегайте оператора "если".
-avoid 'if'
statements.
- избегайте "массированных зум-аутов (масштабированных выходов)"
любой текстуры. Дискретизация текстур на слишком высокой частоте переполнит кэш
текстуры и понизит фреймовый показатель сумасшедшим образом. Выбирайте объекты в
масштабе приблизительно 1:1, или целенаправленно изменяйте размер окна и
закрывайте окна, только чтобы не допустить экстремальных зум-аутов.
-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.
- избегайте sin() и cos() функций, если можете. Если их входные
данные не варьируются от пикселя к пикселю, то нужно рассчитать sin/cos значения
в покадровом уравнении, затем сохранить их в q1-q32, и считывать в свой шейдер
уже оттуда.
-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.
- любой расчет, что приводит к одним и тем же значениям для всех
пикселей на экране, должен быть отгружен в покадровые уравнения Milkdrop, а
затем передан в шейдер через q1-q32 переменные. Эти переменные доступны
непосредственно из всех шейдеров (q1, q2 и т.д.), а также для удобства могут
рассматриваться в качестве float4 (q1-q4 маскируют float4 с названием _qa;
q5-q8 следуют в _qb; и т.д.).
-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.).
- также не делайте расчеты движения/искажения в шейдере искривления,
тн которые вы могли бы сделать в повершинных уравнениях. Они выполняются в ЦПУ,
обладающем огромным ресурсом, который почти никогда не используется полностью;
ЦПУ, хотя и обрабатывает в 1000 раз больше математики, потому что работает для
каждого пикселя, вместо каждой вершины, может использоваться в течении множества
перерывов, которые он может получить. Любые низкочастотные эффекты (значения,
что медленно изменяются по экрану) должны следовать в повершинные уравнения, и
только высокочастотный компоненты движения или деформации должны исходить из
пиксельных шейдеров.
-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.
- имейте в виду, что DirectX компилятор шейдеров является
превосходным по оптимизации; все, что может быть выброшено, будет выброшено.
Такие вещи, как
-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.
- вы можете использовать тип данных "числа половинной точности
(half)" там, где вам не нужна полная точность "числа с плавающей запятой
(float)". Вообще рекомендуется использовать "float" для UV координат и для
значений времени, и "half" для почти всех остальных. Тем не менее, не
переживайте об этом слишком много, потому что большинство графических
процессоров в настоящее время выполняют все процедуры с полной точностью и на
полной скорости - а для старых чипов, которые не делают этого, вероятно, должен
быть очень умный драйвер (если это Nvidia или ATI карта) для авто-подстановки
halfs вместо floats, где это возможно.
-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. прежде чем представлять свои пресеты публике, пожалуйста, убедитесь, что
они хорошо выглядят в КВАДРАТНОМ или ШИРОКОЭКРАННОМ режимах. Если это не так,
проверьте все эти руководящие принципы и вы, вероятно, сможете легко исправить
проблему.
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.
Общая цель дизайна в Milkdrop в том, что касается соотношения сторон,
является подгонка пресета к длинной оси окна, и обрезания всего остального,
причем делая все это без какого-либо растягивания или масштабирования (так все
внутренние пиксели холста кадрируются в масштабе 1:1 на экранные пиксели).
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:
* умножайте XY координаты с помощью значений "aspectx" и "aspecty",
соответственно.
*
multiply XY coords by the values "aspectx" and "aspecty", respectively.
- код шейдера:
-shader code:
* умножайте UV координаты на "aspect.xy", и до их использования
попробуйте какую-нибудь текстуру, чтобы сделать размещение текстуры на экране
должным образом. (Например, если экран достаточно широк, и изображение будет
установлено так, чтобы покрыть всю ширину экрана, то оно будет обрезано в
верхней и нижней части).
*
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.)
* умножайте на "aspect.zw" для того, чтобы подогнать его другим
способом (это будет соответствовать тому, чтобы изображение было видно полностью
в одном измерении, и было уложено плиткой в другом направлении).
*
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).
* вы всегда должны беспокоиться о UV координатах в шейдере
искривления, и до выборки основной текстуры, вы должны умножить на "delta",
которые вы применяете к aspect.xy. В противном случае, в широкоформатном окне,
"дельта" будет на самом деле давать изображение значительно сплющенным, или в
высоком окне, изображение будет удлиненным более вертикально.
* 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.
* величина "ang" является аспектом в повершинных уравнениях, также
как в шейдерах искривления и в композитных шейдерах. Тем не менее, если вы
генерируете свое собственное высокоточное значение "ang", используя atan2(), то
будьте осторожны - вы действительно должны умножить UV на aspect.xy заранее, как
то:
* 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. Следите за быстротой ваших пресетов. Нет ничего, что могло бы так
испортить настроение, как выскакивающий пресет, который задыхается на частоте в
10 кадров в секунду. Поскольку деление в 11 раз медленнее, чем умножение (или
сложение/вычитание), если вы собираетесь разделить большое количество значений
на какое-то одно другое значение, то предварительно разделите величину ("inv =
1/myval;"), а затем умножайте на эту обратную величину все другие значения.
Кроме того, никогда не помещайте в повершинный код те вычисления, которые
являются одинаковым вычислением для каждого пикселя; перенесите их в покадровый
код, а затем, используя q1-q32 переменные, переведите результаты в повершинный
код. Помните, что есть принцип: "Если повершинное уравнение не использует, по
крайней мере, одну из переменных {x, y, rad, ang}, то они должны быть
актуализированы в покадровом уравнении".
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. Создавая свои пресеты, используйте в панели конфигурации опцию
размера сетки по умолчанию, или, по крайней мере, проверьте её прежде, чем
распространять пресеты, и так, чтобы убедиться, что они выглядят правильно при
размере сетки по умолчанию. Если используемая сетка является слишком грубой (или
мелкой), то зритель с размером сетки по умолчанию может столкнуться с
неожиданными "бонусными" эффектами, которые вы, возможно, не предполагали, и
которые могут испортить ваш пресет. Если ваша сетка слишком мелкая, то зритель с
настройками по умолчанию не сможет увидеть все детали, которые вы предполагали,
и это может выглядеть плохо.
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. Попытайтесь создавать свои пресеты в 32-битном режиме видео так,
чтобы его уровни яркости были стандартными. Следует действительно быть
внимательными при проектировании своих пресетов в 16-битном цвете, когда
установлен флажок "исправить розовый/белый артефакт насыщения цвета". Этот
чекбокс подключает дополнительный темный образ, чтобы избежать в 16-битном цвете
чрезмерной насыщенности, которая бывает необходима лишь на некоторых картах.
Если это ваш случай, и вы написали такой пресет, то затем, при его запуске на
другой машине, цвет может оказаться безумно ярким.
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. Не стоит недооценивать силу параметров dx и dy (в повершинных
уравнениях). Некоторые из лучших пресетов базируются именно на использовании dx
и dy. Если вы удалите из пресетов всё, так что не будет никакого движения во
всех них, то вы сможете использовать dx и dy параметры, которые обеспечат точный
ручной контроль над движением. В принципе, все другие эффекты (изменение
масштаба, деформация, вращение и т.д.) являются всего лишь усложненными
абстракциями; и все они могут быть смоделированы с использованием только лишь
параметров {x, y, rad, ang} и {dx, dy}.
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. Если вы
используете переменную "progress" в пресете, убедитесь, что вы опробовали пресет
с несколькими значениями "Время автоматической смены пресета". Самое главное,
избежать использования чего-либо типа функции sin(progress), так как скорость, с
которой "progress" увеличивается может значительно варьироваться от системы к
системе, в зависимости от пользовательских установок.
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. если вы пишете шейдеры, пожалуйста, обратите внимание также на
раздел "Гарантия Качества для Шейдеров", см. выше.
5. if writing shaders,
please also see the 'Quality Assurance
for
Shaders' section above.
д. ОТЛАДКА
-----------------------
h.
DEBUGGING
-----------------------
Одна особенность, о которой авторы пресетов определенно должны быть
осведомлены, это то, что существует переменная функции мониторинга, которая
позволяет контролировать (отслеживать) значение любой покадровой переменной по
вашему выбору. Во-первых, нажмите клавишу "N", чтобы увидеть значение переменной
monitor, которая, вероятно, покажет ноль. Тогда всё, что вам нужно сделать, -
это добавить строчку в покадровое уравнение:
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;
где "х" - переменная или выражение, которое вы хотите контролировать. После
того, как вы нажмёте Ctrl+ENTER, чтобы принять изменения, вы должны увидеть
значение покадровой переменной или выражение в правом верхнем углу экрана!
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
-----------------------
Ниже следует список функций, поддерживаемых анализатором выражений (для
инициализации пресета, покадровых и повершинных уравнений; но НЕ для пиксельных
шейдеров). Список был откровенно вырван из бокса помощь по AVS плагинам от
Джастина Франкела, так как Milkdrop использует анализатор выражений, которые он
написал.
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
*
Preset Authoring Guide
*
ШЕЙДЕР "WARP SHADER" -Error
UV-координаты
Текстурирование подразумевает проецирование растровых или
процедурных текстур на поверхности трехмерного объекта в соответствии с картой
UV-координат, где каждой вершине объекта ставится в соответствие определенная
координата на двухмерном пространстве текстуры. Как правило, многофункциональные
редакторы UV-координат входят в состав универсальных пакетов трехмерной графики.
В картографии цилиндрическая проекция — семейство проекций, которые преобразуют
меридианы в вертикали (U=const), а параллели в горизонтали (V=const). Существует
один шов по меридиану (между U=0 и U=1). Шов можно сделать максимально
незаметным, расположив на его месте океан; также, циклически сместив текстуру,
можно аккуратно прорисовать шов, а затем сместить обратно. Рисованные и
фотографические текстуры используют только две координаты: U и V. В случае
автогенерируемых текстур или мультитекстурирования возможна третья координата —
W, глубина в «континууме текстур». Например, W=0 может быть песком, W=1 —
камнями, промежуточные значения — песком, из которого выглядывают камни.
https://ru.wikipedia.org/wiki/UV-преобразование
*
begin ` home