-Поиск по дневнику

Поиск сообщений в Cos_stub

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 02.08.2007
Записей: 57
Комментариев: 70
Написано: 438


Эффект жидкости

Четверг, 06 Сентября 2007 г. 13:32 + в цитатник
Меня удивляло, как в древней игрушке Quake была анимирована вода. Это был не набор текстур-кадров анимации, а лишь одна текстура, но она чудесным образом деформировалась. Причем это было не линейное преобразование. На то время сложно представить что люди писали пиксельные шейдеры, но в первом квейке они точно есть.
Время Квейка ушло, найти описание как они делали эту примочку мне не удалось, зато глядя на саму воду появились догадки как сделать подобный эффект.
Текстура это квадратный двумерный массив пикселей (более стильно сказать матрица :)). Как массив - можно сделать циклический его сдвиг, например строки вправо или влево, столбца вверх и вниз. Индексы можно рассматривать как координаты х и y. Тогда при сдвиге по горизонтали и вертикали на dx и dy получим Х=x(+/-)dx, Y=y(+/-)dy.
Возьмем синусоиду вида f(x)=a*sin(x*2*Pi/N), где a - амплитуда, х- координата, а N - размер текстуры по горизонтали, f(x) есть округленное целое число. Используем ее для сдвига столбцов матрицы - Х=х,Y=y-f(x). Теперь элемент новой деформированной текстуры X,Y соответствует элементу X,Y+f(X) оригинала. Как результат мы получаем волновую деформацию по горизонтали.
Аналогично возьмем синусоиду вида g(y)=b*sin(y*w*Pi/N),... X,Y соответствует элементу X+g(Y),Y. Получим волновую деформацию по вертикали.
Теперь можно их обьединить, в результате X=x+g(y),Y=y+f(x+g(y)).. хотя можно получить и X=x+g(y+f(x)),Y=y+f(x).
Теперь исходя из практики - считать для каждого пикселя текстуры синус - это тяжело для процессора и глупо. Ведь мы подаем в качестве аргумента целое число в диапазоне от 0 до N-1. Можно заранее вычислить значения синусов 1 раз и записать их в массив, потом просто брать готовые значения.
Анимация деформации делается очень просто, синунусу дается начальнаяя фаза, например r. Проверка на то, вылазит ли индекс за пределы массива легко делается остатком от деления, например (x+a)%N. Но тут получается глюк, в слечае если x+a<0. Допустим сдвиг индекса a по модулю не превышает N, тогда в виде (x+a+N)%N у нас все будет работать нормально. Теперь что касается функции f. Агрументом будет подаваться x,x+a или y+g(x). Пусть она возвращает значения от 0 до N-1 (циклический сдвиг на -1 эквивалентен сдвигу на N-1). Получается что агрументы могут принимать значения от 0 до 2N-2. Конечно можно свести аргументы к 0..N-1 операцией целочисленного деления, но ее можно вообще не делать, если увиличить массив вычисленных значений в 2 раза.
В результате после предварительной подготовки, мы можем получить значение деформированного пикселя X:=(X+G[Y])%N,Y:=(Y+F[X])%N, тут % - остаток от деления. Т.е. 2 сложения, 2 взятия элементов массива и 2 остатка от деления
Рубрики:  Programming Interface
Computer Games Interface

 

Добавить комментарий:
Текст комментария: смайлики

Проверка орфографии: (найти ошибки)

Прикрепить картинку:

 Переводить URL в ссылку
 Подписаться на комментарии
 Подписать картинку