Наложение рисунков и спецэффекты
Затягивание изображения туманом (Fogging) относится к наиболее сложной категории спецэффектов, создаваемых с помощью альфа-наложения. Из собственного жизненного опыта вы знаете, что в тумане наше поле зрения ограничено тем больше, чем плотнее туман. Кроме того, туман рассеивает свет от различных источников, в результате чего он может казаться цветным.
Формулу для выполнения альфа-наложения тумана однородного цвета можно записать в следующем виде:
X[i,j] = Fc[j] * alpha[i] + X[i,j] * (1 – alpha[i])
Здесь FC – цвет тумана, ах– цвет изображения, затягиваемого туманом. Запись Fctj] означает, что каждая точка тумана окрашена в один и тот же цвет, это позволяет избавиться от файла, содержащего изображение тумана. В отличие от ранее приведенных формул, в данном случае у коэффициента alpha появился индекс 1, т. е. значений alpha должно быть столько, сколько точек в основном рисунке (который затуманивается). О том, как подготовить массив значений alpha, мы поговорим после.описания программной реализации формулы.
Если у значений alpha убрать индекс i, то получится формула для наложения прозрачного цвета, которая была реализована в подпрограмме примера 7.31. Следовательно, надо несколько изменить внешний цикл этой подпрограммы, добавив в него выборку значения alpha для каждой точки изображения, что и сделано в примере 7.32. Предполагается, что затягиваемое туманом изображение находится на экране.
Перед вызовом подпрограммы в регистре di указывается адрес начала строки рисунка в видеопамяти, а в fs:si – адрес начала строки коэффициентов alpha в буфере обмена. В сх задается количество точек в строке.
Пример 7.32. Наложение строки тумана заданного цвета.
Foglin: PushReg <bx, dx>; сохранение регистров bx, dx f og_l: push ex; сохранение счетчика повторов lods byte ptr f s: [si]; al = alpha [i] mov byte ptr falpha, al; falpha = al запоминаем alpha [i] push si сохраняем содержимое si lea si, fogcol si = адрес переменной fogcol mov ex, 03 для обработки трех базовых цветов f og_2: lodsb al = базовый цвет тумана (F[j]) mov Ы, es: [di] Ы = базовый цвет точки (Y[i,j]> xor ah, ah преобразуем байт в слово xor bh, bh преобразуем байт в слово sub ax, bx ах = F[j] – Y[i,j] imul falpha ах = ах * alpha [i]; dx = 0 xchg al, ah al = ax/256 add al, Ы al = al + Y[i,j] stosb сохраняем результат в видеопамяти loop fog 2 трехкратное повторение цикла inc di пропуск резервного байта jne @F › адрес в пределах текущего окна call NxtWin установка следующего окна @@: Pop si восстановление адреса в si pop ex восстановление счетчика повторов loop fog 1 управление повторами цикла PopReg <dx, bx> восстановление регистров dx, bx ret возврат из подпрограммы
Значения alpha изменяются от 0 до 255, для сокращения размера файла их лучше хранить в виде байтов, но при умножении коэффициент alpha должен иметь размер слова. Поэтому в примере 7.32 введена специальная переменная falpha, имеющая размер слова. Ее надо описать в разделе данных задачи, присвоив нулевое значение.
Во внешнем цикле примера 7.32, по сравнению с примером 7.31, появились три новые команды. Первая из них считывает очередное значение alpha [i] в регистр al (и увеличивает содержимое si на 1). Вторая копирует содержимое ai в младший байт переменной faipha, а третья сохраняет в стеке адрес, находящийся в регистре si. Таким образом, в результате выполнения этих трех команд получено очередное значение alpha и освобожден регистр si. Теперь в него можно записать адрес переменной, содержащей цвет тумана, для использования во внутреннем цикле, это же делалось и в примере 7.31.
После выхода из внутреннего цикла восстанавливается находившийся в si адрес, и при повторе внешнего цикла будет выбрано следующее значение alpha из буфера обмена.
Для использования описанной подпрограммы надо подготовить файл, содержащий значения коэффициентов alpha. От их расположения в файле зависит способ построения рисунка, поэтому первыми должны располагаться коэффициенты для его верхней, а последними – для нижней строки. В таком случае построение будет производиться в направлении слева направо и сверху вниз, т. е. по наиболее простой схеме. Способ чтения файла в буфер обмена зависит от количества значений alpha. Например, для затягивания туманом всего изображения при разрешении 640x480 точек файл будет содержать 307 200 байтов и его придется считывать по частям.
Следовательно, перед построением риcунка надо вычислить размер считываемой порции данных (количество строк и байтов в порции). Мы это делали неоднократно.