Mapy świateł



Mapy świateł (ang. Lightmap) służą do realizacji oświetlenia sceny. Zasada wykorzystania map świateł opiera się na renderowaniu wielokątów z właściwą teksturą oraz dodatkowo z teksturą mapy oświetlenia. Stosowane są dwie metody renderowania map świateł. Pierwsza metoda polega na równoczesnym renderowaniu tekstury i mapy światła dla tego samego wielokąta i podanego trybu mieszania kolorów tekstury (ang. multi-blender texture operations). Druga metoda polega na dwukrotnym renderowaniu tego samego wielokąta. Pierwszy raz renderujemy wielokąt z właściwą teksturą, drugi raz renderujemy ten sam wielokąt z mapą światła i ustawionym trybem przezroczystości (ang. Alpha blending) oraz odpowiednimi parametrami bufora głębokości (ang. Z-buffer or Depth Buffer).
Poniżej została opisana jedna z metod liczenia składowych koloru dla tekseli mapy światła.

1. Wyznaczamy współrzędne mapy światła lu i lv:

//Wyznaczenie współrzędnych mapy światła
if (fabs(N.x) > fabs(N.y) && fabs(N.x) > fabs(N.z))
{
    Typ = 1;
    for(i = 0; i < IloscWierz; i++)
    {
        Wierz[i].lu = Wierz[i].y;
        Wierz[i].lv = Wierz[i].z;
    }
}
else if (fabs(N.y) > fabs(N.x) && fabs(N.y) > fabs(N.z))
    {
        Typ = 2;
        for(i = 0; i < IloscWierz; i++)
        {
            Wierz[i].lu = Wierz[i].x;
            Wierz[i].lv = Wierz[i].z;
        }
    }
    else
    {
        Typ = 3;
        for(i = 0; i < IloscWierz; i++)
        {
            Wierz[i].lu = Wierz[i].x;
            Wierz[i].lv = Wierz[i].y;
        }
    }

Gdzie:
N i D - to współrzędne płaszczyzny, na której znajduje się wielokąt.
Wierz - to tablica wierzchołków wielokąta.
IloscWierz - to ilość wierzchołków w tablicy Wierz.

2. Normalizujemy współrzędne mapy światła lu i lv:

//Normalizacja współrzędnych mapy światła
minu = Wierz[0].lu;
minv = Wierz[0].lv;
maxu = Wierz[0].lu;
maxv = Wierz[0].lv;

for (i = 0; i < IloscWierz; i++)
{
    if (Wierz[i].lu < minu) minu = Wierz[i].lu;
    if (Wierz[i].lv < minv) minv = Wierz[i].lv;
    if (Wierz[i].lu > maxu) maxu = Wierz[i].lu;
    if (Wierz[i].lv > maxv) maxv = Wierz[i].lv;
}

du = maxu - minu;
dv = maxv - minv;

for (i = 0; i < IloscWierz; i++)
{
    Wierz[i].lu -= minu;
    Wierz[i].lv -= minv;
    Wierz[i].lu /= du;
    Wierz[i].lv /= dv;
}

Dla wszystkich wielokątów sceny zapamiętujemy wartości minu, minv, maxu i maxv oraz Typ.

3. Wyznaczamy trzy wektory mapy światła uvvect, kieru, kierv.
Wektory te służą do wyznaczenia pozycji każdego teksela mapy światła w przestrzeni 3D:

//Wyznaczenie wektorów mapy światła
switch( Typ )
{
    case 1: //YZ

        vectx = - ( N.y * minu + N.z * minv + D ) / N.x;
        uvvect = D3DVECTOR( vectx, minu, minv );

        vectx = - ( N.y * maxu + N.z * minv + D ) / N.x;
        vect1 = D3DVECTOR( vectx, maxu, minv);

        vectx = - ( N.y * minu + N.z * maxv + D ) / N.x;
        vect2 = D3DVECTOR( vectx, minu, maxv);

        break;
    case 2: //XZ

        vecty = - ( N.x * minu + N.z * minv + D ) / N.y;
        uvvect = D3DVECTOR( minu, vecty, minv);

        vecty = - ( N.x * maxu + N.z * minv + D ) / N.y;
        vect1 = D3DVECTOR( maxu, vecty, minv);

        vecty = - ( N.x * minu + N.z * maxv + D ) / N.y;
        vect2 = D3DVECTOR( minu, vecty, maxv);

        break;
case 3: //XY

        vectz = - ( N.x * minu + N.y * minv + D ) / N.z;
        uvvect = D3DVECTOR( minu, minv,vectz);

        vectz = - ( N.x * maxu + N.y * minv + D ) / N.z;
        vect1 = D3DVECTOR( maxu, minv, vectz);

        vectz = - ( N.x * minu + N.y * maxv + D ) / N.z;
        vect2 = D3DVECTOR( minu, maxv, vectz);

        break;
}

kieru = vect1 - uvvect;
kierv = vect2 - uvvect;

Dla wszystkich wielokątów sceny zapamiętujemy wektory uvvect, kieru, kierv.

4. Wyznaczamy składowe koloru dla każdego teksela mapy światła.

//Wyznaczenie składowych koloru
for(x = 0; x < szerokosc; x++)
{
    for(y = 0; y < wysokosc; y++)
    {
        du = x / szerokosc;
        dv = y / wysokosc;

        teksel_poz = uvvect + kieru * du + kierv * dv;

        // tutaj powinien zostać umieszczony program wyznaczający wartości koloru (r, g, b) dla teksel_poz
        // wypadkowy kolor powinien być wyznaczony od kolejnych źródeł światła

        lightmap[x + y * wys * 3] = (char)r;
        lightmap[x + y * wys * 3 + 1] = (char)g;
        lightmap[x + y * wys * 3 + 2] = (char)b;
    }
}

Gdzie:
szerokosc i wysokosc - to szerokość i wysokość mapy światła np. 8, 16, 32 ...
teksel_poz - to pozycja teksela w przestrzeni 3D.
r, g, b - to składowe koloru teksela mapy światła

Autor: Mirosław Kozioł, Komires Sp. z o.o.


Numer artykułu: 5
Wysłany: Sun, Jan 24, 2010 4:31 PM
Ostatnio zmieniony: Sun, Jan 24, 2010 6:32 PM

Adres URL: https://www.komires.net/article.php?id=5