[an error occurred while processing this directive]

2D Bump (Эффект неровной поверхности).

© Федор Цыплаков

Во многих демо используется эффект 2D bump (2D рельефа), когда источник света (чаще всего окружность) двигается по "рельефному" экрану.

Вот как это делается:
  • Освещенность точки зависит от угла между нормалью каждого пиксела, и источником света.
  • Так как вектор нормали имеет три координаты (x,y,z), и мы знаем координаты x и y, то z вычисляется по формуле z=1-sqrt(x*x+y*y). Если непонятно, откуда взялась эта формула -- вам пора вспомнить геометрию ;)
  • Так как в реальном времени это будет очень медленно, то создают заранее таблицу предвыборки, где для каждого X и Y вычисляется значение вектора Z. Эта таблица называется enviroment map (карта окружения). Подобные карты используются и при текстурировании "зеркальных" объектов (что намного проще, чем прямая трассировка :) Обычно хватает карты размером 256х256. Генерить ее можно и с помощью 1-sqrt(x^2+y^2), и с помощью синусов. В общем случае можно использовать любую модель освещения - все зависит от того, что вы хотите получить :) .

    Вот пример построения простейшей карты:
       int i,j;float x,y;
       int density=128; //размер пятна
       int bright; //количество оттенков
    
       for (i=0;i<256;i++){
       for (j=0;j<256;j++){
         x=j/density-1;// (делается для того, чтобы прирвести координаты
         y=i/density-1;//  к значениям от -1 до 1)
         z=1-sqrt(x*x+y*y);
         z=z<0?z:0;
         envmap[i][j]=z*bright;}}
    

    Точка на экране для вышеприведенного случая рассчитывается по формуле result=envmap[X нормали+density][Y нормали+density] (так как точка наибольшей освещенности лежит посредине карты окружения)

    Нормали X и Y рассчитываем так:
                                      xnorm=screen[x,y]-screen[x+n,y],
                                      ynorm=screen[x,y]-screen[x,y+n].
                                      
    Где n - число от (-5 до 5,n!=0) Большие числа приводят к сильному ухудшению картинки. (А может вам и не надо "правильное" отображение ? Тогда можно применять и большие числа) Параметр n влияет на "высоту рельефа". Не забудьте, что при отрицательных значениях n рельеф будет "вдавленным", при n>0 - выпуклым.)

    Это все касается неподвижного источника с координатами (0,0,-бесконечность) Для того, чтобы пятно света двигалось, нужно всего лишь из получившейся нормали вычесть разность координат пиксела (освещенность которого рассчитывается) и координат источника света. Окончательная освещенность точки получается такая:
       result=envmap[(xnorm-(lx-x))][(ynorm-(lx-y))]
    

    Получившееся значение сравнивается с границами допустимого диапазона яркости, и , если нужно, исправляется в соответствии с этой границей.

    Пример.

      lx,ly - координаты источника света.
      x,y - координаты точки на экране и на бамп-текстуре.
      b_low,b_max - минимальный и максимальный доустимый порог освещенности точки.
       for (int y=0;y<200;y++){
       for (int x=0;x<320;x++){
       int xn=(bmap[x][y]-bmap[x+1][y])-(lx-x)+density;
       int yn=(bmap[x][y]-bmap[x][y+1])-(ly-y)+density;
       if (xnb_max) xn=b_low;
       if (ynb_max) yn=b_max;
       screen[x][y]=envmap[xn][yn];}}
    
    Вот, собственно, и все.


Пояснительный пример
Оригинальная версия документа(RAR-архив)

[an error occurred while processing this directive]