· ··--──══[ COOLer issue #1 ]══─---·· · ЭФФЕКТ: ВОДИЧКА (C2H5OH) by GELTORN/STORM -=========ЭФФЕКТ: ВОДИЧКА (C2H5OH)=========- Довольно загадочный, для непосвященных, но простой, эффектик. В основе лежит, все тот же Blur. Я выбрал 8-пиксельный блюр, так как он дает более красивую картинку. Установим палитру так: 0 -> 255 Синий Белый Заведем два буфера: buf1 и buf2, и указатели на них: buf1_ptr и buf2_ptr. Важно понять, что, хоть указатель называется buf1_ptr, но он может указывать совсем не на buf1, а на buf2. Аналогично для buf2_ptr. Далее по тексту, если я буду называть масив buf1_ptr, то имеется в виду тот массив на который, в данный момент, ссылается buf1_ptr. Тоже самое подрaзyмевается под массивом buf2_ptr. Далее я опишу последовательность которую надо проделать для расчета очередного кадра: 1. Если buf1_ptr, действительно указывает на буф1, то заносим в buf1_ptr точки возмущения. 2. Проходимся по всем точкам массива buf1_ptr и buf2_ptr вот таким алгоритмом: 2.1. Складываем значения точек окружающих текущую, в массиве buf1_ptr. 2.2. Делим эту сумму на 4. (Это не опечатка, действительно делить надо на 4) 2.3. Вычитаем из этой суммы значение текущей точки массива buf2_ptr. 2.4. Если результат меньше 0, то результат равен 0. 2.5. Записываем результат в текущую точку массива buf2_ptr. 3. Теперь меняем местами buf1 и buf2 (собственно для этого нам и были нужны указатели): long temp_ptr=buf1_ptr; buf1_ptr=buf2_ptr; buf2_ptr=temp_ptr; 4. Выводим на экран buf2_ptr. В результате получим эффект воды. Но... Неплохо бы было добавить background (какую-нибудь картинку), да еще чтоб волны искажали его. Чтож нет ничего невозможного... Добавим два буфера: pics и screen_end. В pics будем хранить картинку, которую используем в качестве background`а. А screen_end мы будем выводить на экран. Палитру надо взять из считываемой картинки (надеюсь вы прочитали статью об считывании bmp картинок). Как же нам добиться эффекта искажения, из-за преломления лучей света на границе двух разнородных сред? Счаз подумаем. Берем в руки учебник физики 11 класса и находим формулу расчета угла преломленного луча. Пременив знания, полученные на уроках геометрии, выведем формулу, с помощью которой мы будем находить смещение, относительно текущего пикселя, по которому находиться пиксель который и надо вывести на экран вместо текущего: D=h*tg(arcsin(0.75*sin(a))) D-искомое смещение, h-высота слоя воды (высота волны), а-угол между нормалью к поверхности воды в данной точке и вектором наблюдения. COOL!!! тангенс арксинуса синуса, да еще расчет нормали к поверхности, плюс это надо разложить на нахождение смещения по X и Y SUXX!!! SUXX!!!, и еще раз SUXX!!! Конечно можно сделать precalculating, но табличка получиться слишком уж большая. Как же нам быть? Взглянем еще раз на нашу формулу и подумаем, нельзя ее как нибудь сократить. Допустим, что наш расчудесный тангенс арксинуса синуса, есть величина величина постоянная и равная, например 0.25. Опыт показал, что такое допущение вполне возможно, если ширина волны небольшая. Тогда формула значительно упроститься и будет выглядть так: D=h/4 Теперь, чтобы найти координаты нужного нам пикселя, нам надо прибавить к текущим, D: x'=x+D; y'=y+D; В наш алгоритм добавиться: 2.5. ... 2.6. Делим результат на 4, полученное значение прибавляем к текущим x и y. Если x, больше максимально допустимого значения, то х равен максимальному допустимому значению. Аналогичную проверку надо сделать и для y. Считываем по этим координатам из массива pics, число и записываем по текущим координатам в screen_end. Теперь раскажу как модифицировать этот алгоритм чтобы получить более реальное изображение. Недостаток описанного выше метода - смещение не зависит от наклона нормали к поверхности воды. Как же исправить этот недостаток, особо не усложняя алгоритм? Довольно просто. Нам достаточно знать куда наклонена нормаль, тогда мы сможем смещать координаты в соответсвии с этим направлением. Для того чтобы найти смещения по x и y, будем использовать следующие формулы: Dx=(buf1_ptr[x+1][y]-buf1_ptr[x-1][y])>>2; Dy=(buf1_ptr[x][y+1]-buf1_ptr[x][y-1])>>2; Как надо изменить пункт 2.6., вы наверняка догадаетесь сами. Bye... ---(Geltorn/Storm)