Как правило, волновой эффект - это некое искажение изображения, при котором величина искажения меняется от точки к точке на волнистом рисунке. Итак, первая задача - создать «отображение глубины», производящее число для каждого пикселя. Интуитивно карта глубины будет отображать высоту рифленой водной поверхности над исходными пикселями. Отправной точкой для экспериментов может быть
#define X_CENTER 100 // x pixel position of center
#define Y_CENTER 100 // y pixel position of center
#define RADIUS 70 // approximate radius of circular wave train, in pixels
#define WAVELENGTH 10 // wavelength of ripples, in pixels
#define TRAINWIDTH 3.4 // approximate width of wave train, in wavelengths
#define SUPERPHASE 1.5 // phase vel. / group vel. (irrelevant for stills)
// returns a number from -1.0 to 1.0
double depth(int x, int y) {
double dx = x - X_CENTER ; // or int, if the center coords are ints
double dy = y - Y_CENTER ;
double r = (sqrt(dx*dx+dy*dy)-RADIUS)/WAVELENGTH ;
double k = r - (1-SUPERPHASE)*RADIUS/WAVELENGTH ;
double a = 1 / (1.0 + (r/TRAINWIDTH)*(r/TRAINWIDTH));
return a * sin(k*2*PI);
}
Если у вас есть карта глубины (которую можно предварительно рассчитать, если все, что вам нужно, это применить одну и ту же пульсацию ко многим различным изображениям), у вас есть различные варианты действий с ней:
- осветляет или затемняет каждый пиксель пропорционально его глубине
- сдвиньте карту глубины на несколько пикселей по диагонали и осветлите или затемните в соответствии с разницей между сдвинутой и несмещенной картой.
- слегка сдвиньте каждый пиксель в изображении на вектор, пропорциональный разнице между глубиной каждого пикселя и его (скажем) его восточных и южных соседей. Некоторое сглаживание или передискретизация могут быть необходимы для визуально приятного результата, особенно если ваше базовое изображение содержит четкие параллельные оси оси.
Может потребоваться некоторое экспериментирование с их комбинациями и вариациями, чтобы приблизить вашу ментальную картину желаемого эффекта.