Mapy świateł
Numer artykułu: 5 | Ocena: 4/5 z 1 głosów | Ostatnio zmieniony: Sun, Jan 24, 2010 6:32 PM
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;
}
}
{
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;
}
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;
{
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;
}
}
{
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.