Показать сообщение отдельно
Старый 16.09.2009, 14:01   #1
Genius
Знающий
 
Аватар для Genius
 
Регистрация: 02.11.2007
Сообщений: 255
Написано 27 полезных сообщений
(для 43 пользователей)
Статья:Глобальное освещение(Radiosity)

И так,Radiosity - один из методов глобального освещения(Global Illumination,GI).

Радиосити даёт довольно реалистичное освещение нежели простые методы.



Есть open-source реализации Global Illumination рендеринга такие как Toxic(найти можно на SourceForge.net).

Единственный минус GI это довольно таки долгий расчёт из за моножества вычислений так что GI в наше время можно юзать как статическое(фоновое) освещение,заранее расчитаное.

Но со скорым выходом NVIDIA RayTrace Engine(Точное название не помню) возможно GI можно будет выбить в риал тайм,есть конечно уже реализация риал тайм GI от ATI на DirectX 10 где юзаются кубмапы,но и там оно не сильно риал тайм,да и у меня на NVIDIA GeForce 9600 GT почемуто не запускается их пример,найти его можно на developer.amd.com.

А ха да что то я уже в дебри полез ,так Radiosity - не юзает рей трейсинг в то время как просто GI его во всю юзает.

И так реализация:

Я раскажу о повершином Radiosity,но правельнее же конечно юзать лайтмеп(но это отдельная тема).
У нас в сцене есть комнота,все её цвета вершин заполнены чёрным цветом(r=0,g=0,b=0) на потолке комнаты есть лампа - меш все её цвета вершины заполнены белым цветом(r=225,g=225,b=225),начинаем проход по всем мешам\сурфейсам мешей\вершинам сурфейсов,ах да в Radiosity юзается такая штука как Form Factors для определения интенсивности освещёности пикселя,генерируется Form Factor'ы так:

const int RQ = 32; // качество радиосити,чем больше тем круче

float formFactors[RQ][RQ]; // двумерный массив форм факторов RQ*RQ


for(int x=0;x<RQ;x++){
  for(int y=0;y<RQ;y++){
       formFactors[x][y] = sin( float(x)*PI/float(RQ) )*sin( float(y)*PI/float(RQ) );
  }
}
Форм факторы сгенерированы,представляют они из себя это:


тоесть будет токой цикл:


for(int i=0;i<num_meshes;i++)
{
        Mesh* mesh = meshes[i];

        for(int j=0;j<mesh->getNumSurfaces;j++){

             Surface* s = mesh->getSurface(j);
             Vertex* v = s->getVertex();

             for(int k=0;k<s->getNumVertex();k++){
                    бла бла бла...
             }
        }
}
Цикл генерации radiosity освещения:

1) Камера перемещается в позицию вершины k,её направление равно нормали вершины k(в блитце можно для этого заюзать AlignToVector),вьюпорт камеры - x=0;y=0;width=RQ;height=RQ;FOV=90 - обязательно 90.
2) Рисуется вся сцена из текущей позиции камеры(желально вырубить режим куллинга)
3) Считывается кусок backbuffer'а - x=0,y=0,w=RQ,h=RQ.

Далее ЦИКЛ:

unsigned char tmp[3];
for( int x = 0;x<RQ;x++ ){
  for(int y = 0;y<RQ;y++){
    unsigned char r = пиксель[x][y].r;
    unsigned char g = пиксель[x][y].g;
    unsigned char b = пиксель[x][y].b;
    tmp[0] += r * formFactors[x][y];
    tmp[1] += g * formFactors[x][y];
    tmp[2] += b * formFactors[x][y];
  }
}
после делим tmp на RQ*RQ

tmp[0] /= RQ*RQ;
tmp[1] /= RQ*RQ;
tmp[2] /= RQ*RQ;
и прибовляем tmp к цвету вершины k.

ну и так по все вершинам...

Вот как будет выглидеть полностью цикл:

camera->setViewport(0,0,RQ,RQ);
camera->setFov(90);
camera->setAspect(RQ/RQ);

for(int i=0;i<num_meshes;i++)
{
        Mesh* mesh = meshes[i];

        for(int j=0;j<mesh->getNumSurfaces;j++){

             Surface* s = mesh->getSurface(j);
             Vertex* v = s->getVertex();

             for(int k=0;k<s->getNumVertex();k++){
                    camera->setPosition(v[k].xyz);
                    camera->align(v[k].normal);
                    
                    рендерим мир.
 
                    лочим backbuffer.

                    получаем массив пикселей.


                    unsigned char tmp[3];
                
                    for( int x = 0;x<RQ;x++ ){
                        for(int y = 0;y<RQ;y++){
   
                            unsigned char r = пиксель[x][y].r;
                            unsigned char g = пиксель[x][y].g;
                            unsigned char b = пиксель[x][y].b;
                            tmp[0] += r * formFactors[x][y];
                            tmp[1] += g * formFactors[x][y];
                            tmp[2] += b * formFactors[x][y];
                        }
                    }

                    после делим tmp на RQ*RQ 

                    tmp[0] /= RQ*RQ;
                    tmp[1] /= RQ*RQ;
                    tmp[2] /= RQ*RQ;
                    v[k].color.x += tmp[0];
                    v[k].color.y += tmp[1];
                    v[k].color.z += tmp[2];
             }
       }
}
повторяем этот цикл до достижения красивой картинки(обычно это 15-16 итераций)

4 пасса -

16 пассов -


Полезные ссылки:
-http://freespace.virgin.net/hugo.eli.../radiosity.htm
-http://democoder.ru/dcdn_article_view.php?dcid=22

Последний раз редактировалось Genius, 16.09.2009 в 14:12.
(Offline)
 
Ответить с цитированием
Эти 7 пользователя(ей) сказали Спасибо Genius за это полезное сообщение:
ABTOMAT (16.09.2009), Dream (16.09.2009), impersonalis (16.09.2009), Mr_F_ (16.09.2009), NitE (16.09.2009), Randomize (16.09.2009), SBJoker (16.09.2009)