2008-10-15 10 views
8

Mam dane obrazu i chcę uzyskać pod-obraz tego, aby użyć go jako tekstury OpenGL.SubTexturing openGL

glGenTextures(1, &m_name); 
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldName); 
glBindTexture(GL_TEXTURE_2D, m_name); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

Jak uzyskać obraz podrzędny tego obrazu załadowanego jako tekstura. Myślę, że ma to coś wspólnego z używaniem glTexSubImage2D, ale nie mam pojęcia, jak go użyć do stworzenia nowej tekstury, którą mogę załadować. Wywołanie:

glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, xWidth, yHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

doe niczego, co widzę, i nazywając glCopyTexSubImage2D zajmuje tylko część mojego bufora ramki. Dzięki

Odpowiedz

27

Edytuj: Użyj glPixelStorei. Używa się go do ustawienia wartości GL_UNPACK_ROW_LENGTH na szerokość (w pikselach) całego obrazu. Następnie wywołujemy glTexImage2D (lub cokolwiek innego), przekazując mu wskaźnik do pierwszego piksela w podobrazie oraz szerokości i wysokości podobrazu.

Nie zapomnij przywrócić GL_UNPACK_ROW_LENGTH do 0, gdy skończysz.

Ie:

glPixelStorei(GL_UNPACK_ROW_LENGTH, img_width); 
char *subimg = (char*)m_data + (sub_x + sub_y*img_width)*4; 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, subimg); 
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 

Lub, jeśli jesteś uczulony na wyżeł matematyki:

glPixelStorei(GL_UNPACK_ROW_LENGTH, img_width); 
glPixelStorei(GL_UNPACK_SKIP_PIXELS, sub_x); 
glPixelStorei(GL_UNPACK_SKIP_ROWS, sub_y); 

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_data); 

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); 
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); 
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); 

Edit2: Dla uzupełnienia należy wskazać, że jeśli jesteś używając OpenGL-ES, wtedy nie otrzymasz GL_UNPACK_ROW_LENGTH. W takim przypadku można albo (a) wyodrębnić subimage na nowy bufor sam, lub (b) ...

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sub_width, sub_height, 0, GL_RGBA, GL_UNSIGNED_BYTES, NULL); 

for(int y = 0; y < sub_height; y++) 
{ 
    char *row = m_data + ((y + sub_y)*img_width + sub_x) * 4; 
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, sub_width, 1, GL_RGBA, GL_UNSIGNED_BYTE, row); 
} 
+0

Zasadniczo mam obraz (jako surowe dane) i chcę użyć części tego obrazu jako tekstury. Wiem, jak załadować cały obraz jako teksturę, ale nie wiem, jak go wykorzystać. – DavidG

+0

Plakat odpowiedział na to. Jeśli masz obraz w pamięci, jest on w jakiś sposób zapisany. Jeśli używałeś glTexImage2D (... GL_RGBA, GL_UNSIGNED_BYTE) do załadowania, to jest bajt dla wartości R, G, B i alfa. Obrazy są zapisywane z pikselem (0, 0) rozpoczyna się od pozycji 0. Piksel x w wierszu y rozpoczyna się od obrazu [szerokość * y + x] [0] – mstrobl

+0

ponieważ korzystam z OpenGL ES, w końcu wykonałem pierwszy opcja u, czyli wyodrębnianie podwidoku do nowego bufora. Niestety na urządzeniu to już nie działa, więc mam zamiar przerobić teksturę, tak, że nie muszę rozwiązywać problemu. – DavidG

1

Dla tych skazani OpenGL ES 1.1/2.0 w 2018 roku i później, zrobiłem kilka testów z różnymi metodami, jak zaktualizować część tekstury z danych obrazu (obraz ma taki sam rozmiar jak tekstura).

Metoda 1: skopiować cały obraz z glTexImage2D:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels); 

Metoda 2: skopiować cały obraz z glTexSubImage2D:

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_Pixels); 

Metoda 3: Copy część obrazu, linia po linii w pętli:

auto *ptr = m_Pixels + (x + y * mWidth) * 4; 
for(int i = 0; i < h; i++, ptr += mWidth * 4) { 
    glTexSubImage2D(GL_TEXTURE_2D, 0, x, y+i, w, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr); 
} 

Metoda 4: skopiować całą szerokość obrazu, ale pionowo skopiować tylko część, która uległa zmianie:

auto *ptr = m_Pixels + (y * mWidth) * 4; 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, mWidth, h, GL_RGBA, GL_UNSIGNED_BYTE, ptr); 

A oto wyniki testu odbywa się na PC, o 100000 razy aktualizujących różne części tekstury, które stanowiły około 1/5 wielkości całej tekstury.

  • Metoda 1 - 38.17 s
  • Metoda 2 - 26.09 sek
  • Metoda 3 - 54,83 sek - najwolniej
  • Metoda 4 - 5,93 sek - zwycięzca

Nic dziwnego, że metoda 4 jest najszybciej, jak tylko kopiuje część obrazu, a to robi za pomocą jednego wywołania funkcji glTex ...().