Autor Wątek: [c++] Opengl opakowany w obiekty, czy warto?  (Przeczytany 39004 razy)

Offline Q

  • Użytkownik

# Czerwiec 29, 2014, 14:55:35
Nie rozumiesz o co mi chodzi, mam jakiś obiekt np trójkąt. Ustawiam mu teksture i wklejam ileś razy, potem zmieniam texture i znów wypisuje go iles razy, jeśli gl_InstanceID po każdym razie mi sie ustawi na 0 to przesłane macierze do bufora który odpowiada za pozycje staja sie bezwartościowe. Ponieważ trójkąt A i B beda rysowane w tych samych miejscach.
I nie ma znaczenia gdzie ustawie index, lub ile ma mieć indexów.

Offline Mr. Spam

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

Offline DezerteR

  • Użytkownik

# Czerwiec 29, 2014, 15:09:54
A co pisałem ci wcześniej o trzymaniu pozycji w VBO? I ewentualnym aktualizowaniu wedle potrzeby.
Z tego co widzę teraz robisz tak że wysyłasz w uniformie pozycje wszystkich obiektów, rysujesz kilka z nich, zmieniasz texturę, rysujesz(nie wklejasz) resztę, da?
Od biedy możesz wysłać jakiś offset  do ~ID.

Offline albireo

  • Użytkownik

# Czerwiec 29, 2014, 15:57:45
Przypuszczam, że właśnie trzyma pozycje w VBO (glVertexAttribDivisor), i wtedy właśnie jest problem, bo za każdym kolejnym wywołaniem rysuje te same obiekty, ale jeśli potrzebna jest zmiana tekstur, to można skorzystać z tablicy tekstur (array texture) i załatwić wszystko jednym wywołaniem draw*instanced dodając dodatkowy atrybut z numerem tekstury (ewentualnie obliczając go na podstawie gl_InstanceID jeśli się da, np w sytuacji gdy każdą teksturą rysowanych jest tyle samo obiektów).

Offline Q

  • Użytkownik

# Lipiec 03, 2014, 18:28:51
Cytuj
Przypuszczam, że właśnie trzyma pozycje w VBO (glVertexAttribDivisor), i wtedy właśnie jest problem, bo za każdym kolejnym wywołaniem rysuje te same obiekty
Dobrze przypuszczasz :)
Wpadłem na taki pomysł:
// wypisujemy 5 elementów
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT,(GLvoid*)0, 5);
// wypisujemy kolejne 5 elementów
// gl_InstanceID znów jest ustawione na 0
// ale zmieniamy bufor z pozycjami na inny i obchodzimy problem z  gl_InstanceID
/*
 tu podmiana bufora
*/
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT,(GLvoid*)0, 5);

Niestety pojawiły się problemy. Po pierwsze można podmienić dane w samym buforze za pomocą glBufferSubData ale wąże sie to z przesłaniem danych do bufora co jest chyba dość kosztowne czasowo, w dodatku kod:
glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Position2), Position2);
glBindBuffer( GL_ARRAY_BUFFER, 0 );
nic mi nie robi.
Po drugie fajnie było by podmienić jeden bufor na inny już istniejący. Niestety wykracza to poza zakres mojej wiedzy.

Offline DezerteR

  • Użytkownik

# Lipiec 03, 2014, 19:23:18
kuźwa, nie możesz przesłać w uniformie jakiegoś offsetu go gl_InstanceID, ha? Myśl kreatywnie.
I sizeof(Position2) pomnóż przez rozmiar Position2, bo tu ma być podany rozmiar w bajtach całego fragmentu pamięci który wysyłasz.

Offline Q

  • Użytkownik

# Lipiec 03, 2014, 20:18:04
Cytuj
kuźwa, nie możesz przesłać w uniformie jakiegoś offsetu go gl_InstanceID, ha?
Nie czaje

Offline albireo

  • Użytkownik

# Lipiec 03, 2014, 20:44:52
kuźwa, nie możesz przesłać w uniformie jakiegoś offsetu go gl_InstanceID, ha? Myśl kreatywnie.
Przesłanie offsetu nic nie da, bo i tak nie zostanie on uwzględniony w atrybutach z ustawionym glVertexAttribDivisor różnym od zera, jakby sam sobie te dane pobierał (np z tekstury) to by można tego użyć.

Zamiast podstawiania nowego bufora (lub nowych danych w buforze), możesz przestawić początek danych za pomocą glVertexAttribPointer, w ostatnim argumencie dajesz offset do początku danych w bajtach, tyle że wtedy traci się część sensu używania VAO.

Offline DezerteR

  • Użytkownik

# Lipiec 03, 2014, 21:02:53
Q pisze iż zeruje mu się gl_InstanceID, znaczy że go do czegoś używa. Podałem mu więc sposób na zachowanie tej wartości pomiędzy kolejnymi callami.

Najlepiej byłoby chyba aktualizować bufor, przy małej ilości danych i aktualizacji nie powinno być to obciążeniem. Jak mu będzie sprawiało to problem to zapewne będzie miał wystarczającego skilla by sobie z tym poradzić.

A i zawsze może zrezygnować z VAO i pracować na zwykłych VBO, na początek myślę że byłoby mu prościej. 

Offline Q

  • Użytkownik

# Lipiec 04, 2014, 09:28:37
Rozwiązałem problem.
1. tworze 2 bufory przechowujące pozycje np poz1 i poz2.(dla każdego obiektu)
2. podpinam do wiazania w shaderze odpowiedzialnego za pozycje bufor poz1 i wyrysowuje jakiś obiekt z bufora geometrii
3. podpinam analogicznie do tego samego wiazania bufor poz2 i wyrysowuje inny obiekt z tego samego bufora geometrii.

Problem z gl_InstanceID rozwiązany, wszystko wygląda mniej wiecej tak:
glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, 0);
glBindTexture( GL_TEXTURE_2D, tex1 );
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT,(GLvoid*)0, 2);

glBindBuffer(GL_ARRAY_BUFFER, vbo[4]);
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, 0, 0);
glBindTexture( GL_TEXTURE_2D, tex2 );
glDrawElementsInstanced(GL_TRIANGLES, 3, GL_UNSIGNED_INT,(GLvoid *)(3*sizeof(GLuint)), 2);
Wydaje mi sie że powinno działać to szybciej niż napełnianie bufora nowymi danymi.

A teraz to co tygryski lubią najbardziej, zamiana tego na obiekty :P
Tak sobie myślałem że dobrze będzie wprowadzić podział na różne obiekty, np:
Object obiekt1(geo, mat); // jakiś obiekt
scene.add(obiekt1); // dodanie
...
// tu zmiana pozycji obiektu1
...
scene.add(obiekt1); // dodanie nowego obiektu na innej pozycji

// ====== Tutaj nowy typ obiektu =======

Clone clonet1(geo, mat); // jakiś obiekt
scene.add(clone); // dodanie
...
// tu zmiana pozycji clone1
...
scene.add(clone1); // sklonowanie clona na innej pozycji
// bedą też 2 obbiekty jak w 1 przykładzie ale bedzie to ten sam obiekt tylko wyświetlany w 2 pozycjach

Co o tym myślicie?
« Ostatnia zmiana: Lipiec 04, 2014, 09:32:06 wysłana przez Q »

Offline DezerteR

  • Użytkownik

# Lipiec 04, 2014, 10:10:52
Czekaj, w buforze przechowujesz pozycję tylko jednego/kilku obiektów? 
Co do przykładu to jakoś dziwnie nie wygląda, ale jest zbyt ubogi żeby coś o tym powiedzieć.

Offline Q

  • Użytkownik

# Lipiec 04, 2014, 10:23:05
Cytuj
Czekaj, w buforze przechowujesz pozycję tylko jednego/kilku obiektów? 
tak, 1 bufor z pozycjami na obiekt.
Cytuj
Co do przykładu to jakoś dziwnie nie wygląda, ale jest zbyt ubogi żeby coś o tym powiedzieć.
No to tylko koncept.
Chodziło mi o rozdzielenie pojedynczych obiektów od takich które będa występować w dużej ilości.

Offline DezerteR

  • Użytkownik

# Lipiec 04, 2014, 10:35:54
No więc w takim wypadku dużo prościej przesłać pozycję/macierz transformacji w uniformie. Przechowywanie pozycji w buforze ma sens dla wielu takich samych obiektów, np. 1k krzaczków trawy.
Jak masz po kilka obiektów, możesz rysować w pętli.
Wybacz że wprowadziłem cię w błąd ale chyba się wtedy źle zrozumieliśmy.

Offline Q

  • Użytkownik

# Lipiec 04, 2014, 11:43:44
Cytuj
No więc w takim wypadku dużo prościej przesłać pozycję/macierz transformacji w uniformie. Przechowywanie pozycji w buforze ma sens dla wielu takich samych obiektów, np. 1k krzaczków trawy.
To prawda, w dodatku łatwiej jest zmienić potem wartość takiej pozycji ale ma to wady.
Z tego co mi wiadomo (gdzieś wyczytałem i nie wiem czy to prawda) to uniformy mają ograniczenia wielkości. Więc w końcu napotkamy na ograniczenia, a ja tego nie lubie.
Poza tym jak już gdzieś pisałem wcześniej biblioteka nad którą pracuje ma służyć do mojego projektu, a w nim chce wyświetlać ponad 4kk obiektów (nie wiem czy to osiągnę ale cel przyznacie że ambitny).
Wiec tak czy siak muszę się na jakieś rozwiązanie zdecydować.
Cytuj
Wybacz że wprowadziłem cię w błąd ale chyba się wtedy źle zrozumieliśmy.
Nic sie nie stało, dzięki Tobie poczytałem sobie troszkę o offsetach. 

Offline DezerteR

  • Użytkownik

# Lipiec 04, 2014, 11:58:07
Wiesz, wszystko zależy od tego co chcesz wyświetlać, co innego wyświetlać trawę, a co innego czołg z kilkudziesięcioma kośćmi i kilkoma teksturami. 

Uniformy mają jakieś tam ograniczenie, ale jest coś takiego jak Unifom Buffer Object.