3D megjelenítés

3D-ből 2D

Az első alap dolog, amit tudnunk kell az, hogy hogyan lehet egy 3D-s pontot leképezni a 2D-s képernyőre.

Azt tudnunk kell, hogy az egész 3D-t úgy kell elképzelni, mintha egy ablakon (képernyőn) néznénk ki, csak azt kell kiszámolni, hogy a képernyőn hol látszana a pont. Ha tényleg kinéznénk. Ha minden pontot leképeztünk, akkor kész a 3D-s ábra. Ennyi.

Láthatjuk, hogy egy egyszerű párhuzamos szelők tételéből ki lehet hozni azt, hogy hol lesz a pont. Csupán az x és y koordinátákat kell megszorozni z/d-vel, és meg is van a koordináta. A pontot már csak el kell tolni, hogy a távolabbi pontok képe a képernyő közepe felé tartson.

Elég lesz a következő képleteket kiszámolni:

Vagy transzformációs mátrixszal:

Itt lx és ly a képernyőfelbontásának a fele.

Lényegében ennyi. Elég egyszerű.

Vonalak rajzolása 3D-ben

A vonalak rajzolása nem okoz különösebb problémát 3D-ben. Elég egyszerűen kiszámolni a két végpontot, majd egyenes vonallal összekötni őket.

Kitöltött alakzatok (sokszögek) rajzolása 3D-ben

Ha az alakzat egyszínű, akkor a csúcspontok kiszámolása után csak egyszerűen a poligonrajzoló eljárással megrajzoljuk a sokszöget.

Textúrázás

Ha nem csak egyszínű poligonokkal akarunk dolgozni, hanem szeretnénk a poligonokra alakzatot is feszíteni, akkor textúráznunk kell.

A textúrázásnak sokféle módja van.

Kezdjük a legegyszerűbbel.

Faltextúra

Bizonyára mindenki észrevette, hogy régi kezdetleges 3D-s játékokban csak és kizárólag függőleges és vízszintes falak vannak. Továbbá csak téglalap alakúak. Nyilván azért, mert ezeket a legegyszerűbb megjeleníteni.

Vegyünk egy függőleges falat. A hozzánk közelebbi és távolabbi része is ugyanolyan magas, azonban a távolabbi oldala kisebbnek látszik. Ily módon van egy trapézunk, amelynek párhuzamos oldalai függőlegesek, ezért könnyű textúrát feszíteni rá.

Elkezdjük a falat a bal oldalánál render-elni, közben folyamatosan figyeljük, hogy mikor lépünk egy oszloppal arrébb a textúrában. Mindig egy pixelnyi oszloppal lépünk előre, és pixelenként rajzoljuk ki a falat. Az eljárás addig tart, amíg eljutunk a trapézunk jobb oldaláig.

Az renderelő eljárás pszeudokódja (azoknak, akik leakarják ezt programozni):

Paraméterek:

Left: a trapéz bal oldalának X koordinátája

Right: a trapéz jobb oldalának X koordinátája

lt: a trapéz bal felső sarkának Y koordinátája

lb: - || - bal alsó - || -

rt: - || - jobb felső - || -

rb: - || - jobb alsó - || -

lz: a trapéz bal oldalának távolsága (Z koordinátája)

rz: a trapéz jobb oldalának Z koordinátája (az lz-ből is kiszámolható!)

tw: textúra oszlopok száma (példánkban ez 5)

th: textúra sorainak száma (ez is 5 itt)

txw: textúra kép szélessége (pixel)

txh: textúra kép magassága (pixel)

tdata: textúrát tartalmazó tömb

 

Megjegyzések:

Ha tw>txw vagy th>txh, akkor az eljárás a megadott falat kicsempézi a megadott textúrával.

Az X és Y koordináták képernyő-koordinátákban értendők, míg a Z koordináta továbbra is világkoordináta.

 

ELJÁRÁS Render(Left,Right,lt,lb,rt,rb,lz,rz,d,tw,th,tdata[0..txw-1][0..txh-1])

HA Left=Right AKKOR

ELJÁRÁS MEGSZAKÍTÁS

ELÁGAZÁS VÉGE

HA Left>Right AKKOR

Left<=>Right   (Értékcsere)

lt<=>rt

lb<=>rb

ELÁGAZÁS VÉGE

HA lt>lb AKKOR lt<=>lb

HA rt>rb AKKOR rt<=>rb

zdiff:=rz-lz

xdiff:=Right-Left

ytdiff:=rt-lt

ybdiff:=rb-lb

klz:=d/lz

krz:=d/rz

zstep:=zdiff/tw

ytstep:=ytdiff/xdiff

ybstep:=ybdiff/xdiff

xstep:=xdiff/tw

CurrentZ:=lz+zstep

HA kdiff<>0 AKKOR

NextX:=Right-(d/CurrentZ-krz)/kdiff*xdiff

KÜLÖNBEN

NextX:=Left+xstep

ELÁGAZÁS VÉGE

CurrentX:=0

ystart:=lt

yend:=lb

CIKLUS i:=Left-TŐL Right-IG

HA i<0 AKKOR

ystart:=ystart-i*ytstep

yend:=yend-i*ybstep

i:=0

ELÁGAZÁS VÉGE

HA i>FelbontásX AKKOR

ELJÁRÁS MEGSZAKÍTÁS

ELAGAZÁS VÉGE

CIKLUS AMÍG i>NextX

CurrentX:=CurrentX+1

HA kdiff<>0 AKKOR

CurrentZ:=CurrentZ+zstep

NextX:=Right-(d/CurrentZ-krz)/kdiff*xdiff

KÜLÖNBEN

NextX:=Left+(CurrentX+1)*xstep

ELÁGAZÁS VÉGE

HA CurrentX>=tw AKKOR

CurrentX:=tw-1

CIKLUS MEGSZAKÍTÁS

ELÁGAZÁS VÉGE

CIKLUS VÉGE

ystart:=ystart+ytstep

yend:=yend+ybstep

ysediff:=(yend-ystart)/th

tyc:=0

CIKLUS j:=ystart-TÓL yend-IG

HA j<0 AKKOR

tyc:=tyc-j

j:=0

ELÁGAZÁS VÉGE

HA j>FelbontásY AKKOR

CIKLUS MEGSZAKÍTÁS

ELÁGAZÁS VÉGE

tyc:=tyc+1

CurrentY:=Kerekít(tyc/ysediff)   

PixelBeállít(i,j,tdata[CurrentX MOD txw][CurrentY MOD txh])

CIKLUS VÉGE

CIKLUS VÉGE

ELJÁRÁS VÉGE

Egy kis optimalizálás után ez az eljárás elég gyors lehet ahhoz, hogy akár egy DOOM-szerű játékban a falak megjelenítésére lehessen használni.

Persze tovább is fejleszthető. (Például átlátszó részek, eltolt kép, elforgatott textúra stb.)