Autor Wątek: GUI i rysowanie obrazków spoza atlasu  (Przeczytany 1419 razy)

Offline lukaszw

  • Użytkownik

# Marzec 22, 2012, 10:14:44
Witajcie!
Tak sobie rozważam w wolnym czasie (którego praktycznie nie mam ostatnio) pewien problem. Mianowicie: wyobraźmy sobie jakiś system GUI. Aby zwiększyć wydajność używa on atlasu tekstur, który zawiera wszystkie elementy występujące standardowo w tym GUI. I teraz chcę sobie narysować na jakiejś kontrolce obrazek, którego nie ma w atlasie (ot choćby jakiś awatar). Jeżeli to zrobię tak po prostu, to będzie trzeba zmienić teksturę podczas rysowania, a następnie ewentualnie ponownie zmienić w celu narysowania pozostałych kontrolek. No i teraz pojawia się moje pytanie: jak to rozwiązać? Na pewno ktoś już wpadł na pomysł na obejście tego :)
Pozdrawiam.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline voytech

  • Użytkownik

# Marzec 22, 2012, 12:10:38
Możesz tego avatara zapisać w dowolnej chwili do tekstury z kontrolkami (np. glTexSubImage2D). Obrazki kontrolek raczej nie zajmą całej powierzchni tekstury i jakieś wolne miejsce się na niej znajdzie.

Offline hashedone

  • Użytkownik

# Marzec 22, 2012, 13:03:22
A nawet jeśli są idealnie dopasowane, to możesz specjalnie zarezerwować powierzchnię na ten cel specjalną (dać czarną plamę na atlasie).

Offline pablop

  • Użytkownik

# Marzec 22, 2012, 13:38:57
Jeśli nie zmiana tekstury, to ew. zmiana jednostki teksturowania: do pierwszej jednostki bindujesz atlas, a druga wykorzystujesz do inny tekstur. Musisz wtedy wlączyć drugą jednostke i wylaczyc pierwsza na początku rysowania (ew. ustawic dla drugiej jednostki glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) i mozna rysowac obiema).  Taki pomysl na gorąco :)

Pozdrawiam

Offline Paweł

  • Użytkownik

# Marzec 22, 2012, 15:37:54
U mnie gui trzyma tylko indeks do struktury opakowującej teksturę/atlas:
struct Texture{

  float xTx, yTx, wTx, hTx; //texcoordy
  GLuint glTex;
};

struct Textures{
  int loadTexture(char const* name);
  int loadAtlas(char const* datName, char const* prefix="");
 // jesli nie znajdzie tekstury to spróbuje załadować i zwrócić wskażnik
  Texture* getLoadTexture(char* const name);
  Texture* getTexture(int index); 
 
  std::vector<Texture> loaded;
};

loadTexture przyjmuje jako parametr nazwe pliku z teksturą, a zwraca index (uchwyt) textury; ten index trzyma gui.
loadAtlas przyjmuje jako parametry:
-nazwe pliku textowego z informacjami o atlasie: jakie w nim są tekstury i jakie mają texcoordy;
-prefix jaki każda tekstura z atlasu ma mieć dołączony, np: loadAtlas("a1.dat", "a1/"); i pobranie textury z tego atlasu: getLoadTexture("a1/sometexture.png"); Jeśli  sometexture.png nie będzie w atlasie a1 to zostanie przeszukany folder a1. Jako że generuje atlas z folderu tekstur to nie muszę za każdym razem po dodaniu tekstury do folderu przebudowywać atlasu.
Rozwiązanie to promuje używanie atlasów, dodatkowo atlas mam tak wygenerowany że nie ma znaczenia czy pod indeksem mam teksturę z atlasu czy pojedyńczą.

Offline lukaszw

  • Użytkownik

# Marzec 22, 2012, 18:12:59
Możesz tego avatara zapisać w dowolnej chwili do tekstury z kontrolkami (np. glTexSubImage2D). Obrazki kontrolek raczej nie zajmą całej powierzchni tekstury i jakieś wolne miejsce się na niej znajdzie.
A nawet jeśli są idealnie dopasowane, to możesz specjalnie zarezerwować powierzchnię na ten cel specjalną (dać czarną plamę na atlasie).
A co jeżeli będę potrzebował narysować więcej takich obrazków, które dodatkowo mogą się zmieniać co chwilę? Takie ciągłe aktualizowanie tekstury pewnie byłoby wolniejsze od po prostu zbindowania innej. (W przypadku z duża ilością często zmieniających się obrazków - w innych przypadkach może być lepiej)
Jeśli nie zmiana tekstury, to ew. zmiana jednostki teksturowania: do pierwszej jednostki bindujesz atlas, a druga wykorzystujesz do inny tekstur. Musisz wtedy wlączyć drugą jednostke i wylaczyc pierwsza na początku rysowania (ew. ustawic dla drugiej jednostki glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE) i mozna rysowac obiema).
Jak z wydajnością tego będzie?
U mnie gui trzyma tylko indeks do struktury opakowującej teksturę/atlas:
To akurat nie jest chyba tutaj tak bardzo istotne. W moim problemie chodzi po prostu o być może niepotrzebną minimalizację zmian tekstury podczas rysowania gui ;)

Offline voytech

  • Użytkownik

# Marzec 23, 2012, 11:00:50
A co jeżeli będę potrzebował narysować więcej takich obrazków, które dodatkowo mogą się zmieniać co chwilę? Takie ciągłe aktualizowanie tekstury pewnie byłoby wolniejsze od po prostu zbindowania innej.
Jak nie pomierzysz to nie będziesz wiedział.

Tekstura 1024x1024 zmieści 100 avatarów każdy 100x100 pikseli. To moim zdaniem dużo. Jak potrzebujesz więcej miejsca bo masz dużo więcej obrazków albo są one większe to można przydzielić większy rozmiar tekstury albo nawet skorzystać z GL_EXT_texture_array.

glTexImage3D(GL_TEXTURE_2D_ARRAY, ..);
glBindTexture(GL_TEXTURE_2D_ARRAY, ..);

jedno bindowanie i masz dostęp do większej ilości tekstur. Nie mam pojęcia jak będzie z wydajnością takiego rozwiązania ale chyba nie powinno być jakiś większych problemów.

Offline lukaszw

  • Użytkownik

# Marzec 23, 2012, 13:03:49
No w sumie to to może zadziałać :) Jak w końcu znajdę odpowiednią ilość wolnego czasu, to spróbuję potestować. Dzięki wszystkim za rady.