Mostanság szembesültem Unity3D-ben olyannal, hogy az egyébként egyszerűnek tűnő feladat, miszerint néhány vonalat kellene kirajzolni, nem is olyan triviális. Néhány, a felhasználó által megadott pont által határolt területet akartam körberajzolni. Összefoglalom a három megvizsgált módszerrel kapcsolatos tapasztalataim.
Első közelítésben kézen fekvőnek tűnt, hogy a LineRenderert válasszam. Komoly korlátja, hogy csak folytonos vonalat tud kezelni, így ha külön lévő vonalakra van szükség, akkor ahhoz annyi LineRenderer példányra van szükség.
Másik negatívuma, bizonyos csillagállás mellett, megváltozik a vonalvastagság, eltorzulnak a vonalak. Ez a jelenség a LineRenderer működéséből adódik: nem 1 pixeles vonalat rajzol, hanem egy textúrázható, változtatható szélességű sávot (billboardot). Ebből adódik időnként az alábbi képen ábrázolt szituáció.
A LineRenderer a piros pontokat kapja meg kezdő- és végpontnak, a zöldeket pedig magának hozza létre a fentebb leírt működéshez. Előfordul azonban, hogy felcserélődnek a végpontnál lévő zöld pontok, ekkor torzul el a vonalszegmens. Ez különösen akkor jön elő, ha több szegmensből áll a vonal és erős az irányváltás az egyes szegmenseknél, mivel próbál optimalizálni és újrahasznosítja ezeket a zöld pontokat.
Magas szintű grafikai függvénykönyvtár arra, hogy közvetlenül lehessen mesh-t kirajzolni anélkül, hogy létre kellene hozni hozzá GameObjecteket és komponenseket. Ez utóbbi miatt gyorsabb a LineRenderernél, viszont alacsonyabb szintű a vezérlése, vagyis nekem kell ténylegesen létrehoznom a vonalakat. Körülményesebb, de nagyobb szabadságfokot biztosít.
Maga a mesh felülethálóból épül fel, így egy vonal lényegében egy nagyon vékony négyszögként áll elő. Egy ilyen négyszög (quad) 4 vertexből áll, amihez nincs másra szükség csak a kezdő- és végpontokra illetve a vonal vastagságára.
Vector3 normal = Vector3.Cross(start, end);
Vector3 side = Vector3.Cross(normal, end-start);
side.Normalize();
Vector3 a = start + side * (lineWidth / 2);
Vector3 b = start + side * (lineWidth / -2);
Vector3 c = end + side * (lineWidth / 2);
Vector3 d = end + side * (lineWidth / -2);
Vector3 side = Vector3.Cross(normal, end-start);
side.Normalize();
Vector3 a = start + side * (lineWidth / 2);
Vector3 b = start + side * (lineWidth / -2);
Vector3 c = end + side * (lineWidth / 2);
Vector3 d = end + side * (lineWidth / -2);
Először meghatározzuk a normál-vektorát annak a síknak, amiben lesz a vonal. Ezután a side vektor a vonal oldalirányának a síkját jelöli ki, majd a normalizálással lesz belőle egységvektor. Végül ki kell számolni a tényleges vertexeket, amik megadják a quadot.
A felmerült problémára ez is teljes értékű megoldás lett volna, viszont indokolatlanul körülményes az implementáció a feladat mértékéhez képest.
GL osztály
Alacsony szintű és ezzel együtt közvetlen hozzáférést biztosít a rajzoló funkcionalitáshoz egy, az OpenGL-hez hasonló eszköztárral. Ez egyben az előnye és hátránya is, hiszen ez a leggyorsabb, ellenben kevesebb ráhatásom van, például nem állítható közvetlenül a vonalvastagság.
A GL osztálynál megemlítik a hivatalos oldalon, hogy az esetek nagyobb részében hatékonyabb a Graphics.DrawMesh használata, majd folytatják, hogy ezzel szemben sokkal körülményesebb a Graphics-ot kezelni a mesh miatt.
Ajánlott néhány dolgot észben tartani. Az OpenGL sajátossága miatt itt is normalizált viewporttal, képernyőtérrel kell számolni, azaz felbontástól függetlenül a képernyő bal alsó sarka mindig (0,0), míg a jobb felső (1,1) koordinátákkal címezhető. Továbbá bármennyire is adja magát, hogy tetszőleges shadert beállítsunk a GL használatakor a materialra, valamiért csak a honlapon írt "Hidden/Internal-Colored" beépített shader működött. Egyéb shadert kiválasztva a rajzoláshoz megadott színnek csak az alfáját volt hajlandó kezelni, az RGB értéket nem, így fixen fekete volt.
Összegezve
LineRenderert semmilyen körülmények között nem ajánlom, nemdeterminisztikus, mikor torzul el a vonal. Amennyiben a kényelmi funkcionalitás számít, akkor a Graphics, ha pedig a teljesítményen, a sebességen van a hangsúly, akkor egyértelműen a GL a jó választás szerintem.
Alacsony szintű és ezzel együtt közvetlen hozzáférést biztosít a rajzoló funkcionalitáshoz egy, az OpenGL-hez hasonló eszköztárral. Ez egyben az előnye és hátránya is, hiszen ez a leggyorsabb, ellenben kevesebb ráhatásom van, például nem állítható közvetlenül a vonalvastagság.
A GL osztálynál megemlítik a hivatalos oldalon, hogy az esetek nagyobb részében hatékonyabb a Graphics.DrawMesh használata, majd folytatják, hogy ezzel szemben sokkal körülményesebb a Graphics-ot kezelni a mesh miatt.
Ajánlott néhány dolgot észben tartani. Az OpenGL sajátossága miatt itt is normalizált viewporttal, képernyőtérrel kell számolni, azaz felbontástól függetlenül a képernyő bal alsó sarka mindig (0,0), míg a jobb felső (1,1) koordinátákkal címezhető. Továbbá bármennyire is adja magát, hogy tetszőleges shadert beállítsunk a GL használatakor a materialra, valamiért csak a honlapon írt "Hidden/Internal-Colored" beépített shader működött. Egyéb shadert kiválasztva a rajzoláshoz megadott színnek csak az alfáját volt hajlandó kezelni, az RGB értéket nem, így fixen fekete volt.
Összegezve
LineRenderert semmilyen körülmények között nem ajánlom, nemdeterminisztikus, mikor torzul el a vonal. Amennyiben a kényelmi funkcionalitás számít, akkor a Graphics, ha pedig a teljesítményen, a sebességen van a hangsúly, akkor egyértelműen a GL a jó választás szerintem.
Szerintetek van ezeknél kényelmesebb, hatékonyabb esetleg csak szebb megoldás arra, hogy kirajzolhassunk valamilyen egyszerű alakzatot Unity3D-ben?
Nincsenek megjegyzések:
Megjegyzés küldése