Автоматично текстуриране на терен

Преводни и оригинални статии в областта на разработката на игри.
gemicha
Site Admin
Site Admin
Мнения: 2930
Регистриран: 20 ное 2003 22:20
Местоположение: USA

Автоматично текстуриране на терен

Мнение от gemicha » 05 мар 2004 13:47

<center>
Автоматично текстуриране на терен
Автор: Александър Рядков
alex79riadkov@abv.bg
</center>

Въведение

И така в един момент се стига до терена :) искаме да е голям, искаме да е шарен искаме това и онова! През цялото време сме чели за оптимизации на външни и вътрешни пространства, чували сме за осмични дървета, за четвъртични, за двоични и какво ли още не. Само едно не ни е ясно! Как този така великолепно “оптимизиран” терен да бъде текстуриран :). Както и сам успях да разбера, тази задача явно е най-тънката :) (тук се сещам за хората – “които са по тънката част”) понеже за нея има най-оскъдна информация в мрежата.

Варианти за терен

Но нека започнем от самия терен, от неговото устройство. На какво ще е основан? На височинна карта, на геометрия получена от 3D софтуер или на друг способ за получаване? Напълно е възможно да се използва височинна карта, само две неща ме притесняват в този случай... доста големия обем данни и невъзможността да се получат пещери. И понеже бих искал да имам пещери ще трябва да се откажа от услугите на височинните карти :) За това право към Maya и това което тя може да ни даде. Понеже Maya е 3D софтуер можем да си измоделираме какъвто си искаме терен.

Текстуриране

Нека приемем терена за готов (вервайте ми ще стане :) ). Остава самото тестуриране. Ако се намери правило по което да се налага текстурата, освен това ако се намери начин за смесване на автоматично с “ръчно” текстуриране и най-после ако се намери начин броя на текстурите да е почти неограничен...

В най-простия случай върху целия терен могат да бъдат “разхвърлени” пет текстури. За начало не е зле :). В последствие ще стане ясно, че броят на текстурите е наистина неограничен (поне от алгоритъма!).

<img src="http://gamedev-bg.net/img/terrain/screenshot00.JPG" />

<img src="http://gamedev-bg.net/img/terrain/screenshot01.JPG" />

<img src="http://gamedev-bg.net/img/terrain/screenshot02.JPG" />

<img src="http://gamedev-bg.net/img/terrain/screenshot03.JPG" />

В ниското е трева, по високите части е скала, а по върховете има камъни, камъни има и по отвесните части.

Алгоритъмът

Алгоритъма използва височината на всеки връх, за да изчисли абсолютната височина на върха в терена, и нормалата за да изчисли наклона. По тези две стойности (сведени в интервала [0.0f,1.0f]) се индексира пиксел от следната карта.

<img src="http://gamedev-bg.net/img/terrain/lookup.JPG" />

Цветът на този пиксел се назначава като цвят за съответния връх.

Малко код изглежда така:

Код: Избери всички

DWORD _dwcolor = 0;
FLOAT _fslope0 = 0.0f,_fslope1 = 0.0f,_fslope2 = 0.0f;
FLOAT _fheight0 = 0.0f,_fheight1 = 0.0f,_fheight2 = 0.0f;

D3DXCreateTextureFromFile(_pd3ddevice, "lookup.dds", &_pd3dlookup);

_pd3dlookup-> LockRect(0, &_d3dlockedrect, NULL, 0);

//наклона се изчислява като скаларно умножение между нормалата на върха и вектора //(0,1,0)
_fslope0 = (FLOAT)fabs(D3DXVec3Dot(&_v3n0, &_v3up));
_fslope1 = (FLOAT)fabs(D3DXVec3Dot(&_v3n1, &_v3up));
_fslope2 = (FLOAT)fabs(D3DXVec3Dot(&_v3n2, &_v3up));

//намирам и височините за трите върха
_fterrainheight = (FLOAT)fabs(m_vmin.y) + (FLOAT)fabs(m_vmax.y);
_fheight0 = _v4v0.y + (FLOAT)fabs(m_vmin.y);
_fheight1 = _v4v1.y + (FLOAT)fabs(m_vmin.y);
_fheight2 = _v4v2.y + (FLOAT)fabs(m_vmin.y);

if(_fterrainheight != 0.0f)
{
	_fheight0 /= _fterrainheight;
	_fheight1 /= _fterrainheight;
	_fheight2 /= _fterrainheight;
}

//сега вече мога да адресирам пикселите от картата за всеки връх
_dwpixelx = (DWORD)(255 * _fheight0);
_dwpixely = (DWORD)(255 * _fslope0);

_dwcolor = *(PDWORD)((PBYTE)_d3dlockedrect.pBits + (_d3dlockedrect.Pitch * _dwpixely) + (_dwpixelx * 4));

//проверявам дали върха има цвят ако има то ще използвам стария
if(
_pvertices[_wvertex0].m_vcolor.x == 0.0f
 &&
 _pvertices[_wvertex0].m_vcolor.y == 0.0f
 &&
 _pvertices[_wvertex0].m_vcolor.z == 0.0f
 &&
 _pvertices[_wvertex0].m_vcolor.w == 0.0f)
{
_pvertices[_wvertex0].m_vcolor.x = (FLOAT)((FLOAT)LOBYTE(HIWORD(_dwcolor)) / (FLOAT)255.0f);

_pvertices[_wvertex0].m_vcolor.y = (FLOAT)((FLOAT)HIBYTE(LOWORD(_dwcolor)) / (FLOAT)255.0f);

_pvertices[_wvertex0].m_vcolor.z = (FLOAT)((FLOAT)LOBYTE(LOWORD(_dwcolor)) / (FLOAT)255.0f);

_pvertices[_wvertex0].m_vcolor.w = (FLOAT)((FLOAT)HIBYTE(HIWORD(_dwcolor)) / (FLOAT)255.0f);
}

//....

//...
_pd3dlookup->lpVtbl->UnlockRect(_pd3dlookup, 0);

И така по височината и нормалата на върха се намира цвят който после се използва при смесване на текстурите. Когато височината расте тревата постепенно преминава в камъни, когато наклона расте отново се преминава в камениста настилка. В междинните случаи се наблюдава почва.

Как точно се смесват текстурите? Следната формула ще хвърли светлина по въпроса.

Код: Избери всички

color = t1*c1 + t2*c2 + t3*c3 + t4*c4 + … + tn*cn
(където c1 + c2 + … + cn = 1)
Понеже цветът има четири канала то тегловите коефициенти могат да бъдат най-много пет. Пропускам вертекс шейдър функцията и преминавам към пиксел шейдър функцията. Която има следния вид:

Код: Избери всички

psoutput ps(psinput input)
{
    psoutput _output = (psoutput)0;
    float4 _f4texcolor0,_f4texcolor1,_f4texcolor2;
    float _flastweight = 0.0f;
 	
    _f4texcolor0 = tex2D(colormapsampler0, input.f2tex0);
    _f4texcolor1 = tex2D(colormapsampler1, input.f2tex0);
    _f4texcolor2 = tex2D(colormapsampler2, input.f2tex0);

    _flastweight = 1.0f - (input.f4color.x + input.f4color.y);

    _output.f4color.x = _f4texcolor0.x * input.f4color.x + _f4texcolor1.x * input.f4color.y + _f4texcolor2.x * _flastweight;
    _output.f4color.y = _f4texcolor0.y * input.f4color.x + _f4texcolor1.y * input.f4color.y + _f4texcolor2.y * _flastweight;
    _output.f4color.z = _f4texcolor0.z * input.f4color.x + _f4texcolor1.z * input.f4color.y + _f4texcolor2.z * _flastweight;

    return _output;
}
В този случай бяха смесени три текстури.

Различни начини

Как може да се задават цветове на върховете предварително? Ясно е, че ако има предварително зададен цвят няма да бъде установен новия и така ще можем да направляваме текстурирането от Maya. Следните четири картинки ще отговорят и на този въпрос.

<img src="http://gamedev-bg.net/img/terrain/screenshot04.JPG" />

<img src="http://gamedev-bg.net/img/terrain/screenshot05.JPG" />

<img src="http://gamedev-bg.net/img/terrain/screenshot07.JPG" />

<img src="http://gamedev-bg.net/img/terrain/screenshot08.JPG" />

Какво ако три или пет текстури са напълно недостатъчни за целия терен? Просто добавете материал и ще имате още поне толкова :) . В .x файл това изглежда така:

Код: Избери всички

Material initialShadingGroup {
     0.400000;0.400000;0.400000;1.000000;;
     0.000000;
     0.400000;0.400000;0.400000;;
     0.000000;0.000000;0.000000;;

     EffectInstance {
      "grass_stones_soil.fx";

      EffectParamString
      {
       "colormap0";
       "tile2.dds";
      }
	EffectParamString
      {
       "colormap1";
       "tile1.dds";
      }
    	EffectParamString
      {
       "colormap2";
       "tile3.dds";
      }
     }
    }

    Material grass_soil_stones {
     0.400000;0.400000;0.400000;1.000000;;
     0.000000;
     0.400000;0.400000;0.400000;;
     0.000000;0.000000;0.000000;;
     
     EffectInstance {
      "grass_stones_soil.fx";

      EffectParamString
      {
       "colormap0";
       "grass.dds";
      }
	EffectParamString
      {
       "colormap1";
       "soil.dds";
      }
    	EffectParamString
      {
       "colormap2";
       "stones.dds";
      }
     }
    }
Просто подменям текстурните файлове. Нормално е когато за даден материал се използват различен брой текстури и PS функцията да бъде пренаписана подходящо.

<img src="http://gamedev-bg.net/img/terrain/screenshot09.JPG" />

Бях назначил различен материал за някои части около хълма. Така веднага си пролича, че типовете трева са вече два, освен това се появи и почва. Естествено трябва да се внимава за цветовете на върховете по границата на материала или да се използват съвпадащи текстури за да се замаскира прехода от материал в материал.

Ще се намерят хора да попитат за пещерата :), е няма такава!

Това е засега. Вероятно в следващата статия ще добавя вода и/или трева :).

Заключение

Този начин за текстуриране нито е добър, нито е непременно лош. Вероятно ще са нужни няколко опита докато се получи желаният терен. Липсва нагледност, и какво ще се получи става ясно чак след експорта на терена... това е лек недостатък все пак. Като цяло това е отличен метод за бързо спретване на терен за игра. И мисля че може да се използва с успех.

Използвани материали:
http://www.delphi3d.net/articles/viewar ... aintex.htm

Отговори