2012-08-14 17 views
5

Obecnie pracuję nad odgórnym RPG 2d napisanym w Javie 1.6 z LWJGL. Zaimplementowałem wykorzystanie VBO do mojej gry i teraz utrzymuję dwa z nich: jeden dla danych werteksów i jeden dla tekstur.Aktualizacja danych VBO za pomocą glBufferSubData()

Wszystko działa dobrze, z tym że nadal nie mam naprawdę logicznego sposobu aktualizowania obiektów. Na przykład, jeśli chcę, aby określona płytka zmieniła teksturę (zmieniła współrzędne tekstury wewnątrz VBO, aby pokazać inny obszar Arkusza Tekstury), nie widzę sposobu na zmianę tylko współrzędnych tekstury, które odpowiadają ta pojedyncza płytka. Wszystko, co mogę teraz myśleć, to być może wypełnienie buforów wszystkimi danymi potrzebnymi w każdej pętli i przesłanie ich z glBufferData do każdej klatki. Działa, ale nie wydaje się najlepszym sposobem na zrobienie tego (lub robi to?).

Teraz istnieje polecenie glBufferSubData, które nie przydzieli nowej pamięci, a jedynie zmieni porcję, którą polecam zmienić. Chodzi o to, że nie wiem, jak śledzić obszar, który należy zmienić (przesunięcie). LWJGL oferuje glBufferSubData (cel, offset, dane); polecenie, które wymaga jedynie uruchomienia bufora. Czy przesunięcie jest podobne do indeksu?

Więc gdybym najpierw przesłać te bufory do VBO i potem chce zmienić drugą wartość drugiego pływaka []:

FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices * vertexSize); 
vertexData.put(new float[]{100, 100, 300, 100, 300, 300, 100, 300}); 
vertexData.put(new float[]{400, 100, 600, 100, 600, 300, 400, 300}); 
vertexData.flip(); 

Chciałbym wygenerować nowe dane, umieścić go wewnątrz małej FloatBuffer i wgrać go za pomocą glBufferSubData (GL_VERTEX_ARRAY, 10, newFloatBuffer) ;? 10 jest, ponieważ chcę zmienić wartości z dziesiątej starej wartości na.

Czy to prawda? Czy istnieje lepszy sposób na zrobienie tego? I znowu: czy jest w porządku, jeśli ponownie prześlę wszystkie dane w każdej ramce?

+0

Istnieją prostsze sposoby na zrobienie tego. Albo po prostu narysuj tę samą geometrię z inną teksturą. Lub robisz modyfikację współrzędnych tekstury w vertex shader. –

Odpowiedz

6

LWJGL'sglBufferSubData() oczekuje przesunięcia jako liczby bajtów, ponieważ należy umieć zapisywać dowolne dane w dowolnych lokalizacjach buforowych. Jeśli chcesz zaktualizować wartość float na indeksie i, przesunięcie będzie wynosić i * 4, ponieważ java floats przyjmuje, bardzo często, 4 bajty. Pozostała zawartość bufora zostanie zapisana, dlatego wymagany jest bufor docelowy o pojemności co najmniej
(i + floatBuffer.remaining()) * 4 bajtów. Aby uzyskać prawidłowe przygotowanie, zobacz metodę buforowania flip() lub użyj position(int) wraz z limit(int), aby określić pozostałą zawartość do zapisania.

Ta strategia aktualizacji jest OK, o ile nie wywołasz zbyt wiele razy glBufferSubData() z tymczasowymi opcjami FloatBuffers. Można również uzyskać drugi bufor docelowy o takiej samej wielkości do zamiany (ping pong), który można mapować przy użyciu MapBuffer() dla ogólnej aktualizacji, podczas gdy druga jest w użyciu.

Wolałbym posiadać pełny FloatBuffer po stronie klienta i przesłać go na raz za pomocą glBufferData() zamiast wielokrotnie dzwonić pod numer glBufferSubData(). Ale bez znajomości liczb trudno powiedzieć.

+0

Dziękuję bardzo. Zaimplementuję strategię FloatBuffer klienta i zatrzymam ją na razie. Później spróbuję procesorów wierzchołków. – Thiago

+0

Nie ma za co! Shadery to interesujący obszar. Jeśli musisz zmienić obszar tekstur o jednakowej wielkości, tekstury tablic są alternatywą dla mapy/arkusza tekstury. Tekstury 3D można wykorzystać do płynnego mieszania zmiany. – Sam