Twoje pytanie wydaje się mylić niektóre pojęcia, więc weźmy rzeczy z góry. Oto definicja funkcji glTexImage2D
:
void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );
Istnieją dwie rzeczy, które możesz nazwać „formatami tekstur”. Pierwszy to internalformat
parametr. To jest prawdziwy format obrazu, gdy OpenGL go przechowuje. Ten format
parametr opisuje część formatu danych pikseli, które podajesz z data
parametrem.
Ujmując to w inny sposób, format
i type
określić, co wasze spojrzenia danych podoba. internalformat
tak mówisz OpenGL, aby zapisywał twoje dane. Nazwijmy format
i type
„format transferu piksel”, zaś internalformat
będzie „Format obrazu”.
Format obrazu tekstury nigdy nie może być „bgr8”. Nie ma modułu wyliczającego format obrazu GL_BGR8. Jest to enum GL_BGR, ale to jest na formatce przelewu pikseli, a nie format obrazu.
Innymi słowy, dane w pikselach, które podajesz OpenGL, mogą być przechowywane w kolejności BGR. Ale implementacja OpenGL sama decyduje, jak faktycznie przechowywać dane pikseli. Może przechowuje to w porządku little-endian. Może przechowuje to big-endian. Może po prostu arbitralnie porządkuje bajty. Nie wiesz, a OpenGL nie zapewnia sposobu na sprawdzenie.
Nie ma sposobu, aby stwierdzić, czy określony zestaw parametrów formatu transferu pikseli pasuje do sposobu, w jaki implementacja OpenGL będzie je przechowywać, biorąc pod uwagę format obrazu.
Jest teraz sposób, aby powiedzieć. I przez „teraz” mam na myśli w OpenGL 4.3 i / lub ARB_internalformat_query2. Zbliżasz się do karty graficznej w pobliżu:
GLenum format, type;
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, &format);
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, &type);
format
a type
teraz mają preferowaną implementację format
i type
używają glTex(Sub)Image
wywołań GL_RGBA8
obrazów. Istnieją osobne format
i type
zapytania dotyczące glReadPixels
pobierania.
Istnieją inne zapytania, które możesz zadać .
Jeśli nie masz do nich dostępu, możesz zastosować ogólne zasady, których będzie przestrzegać większość sprzętu:
- będzie przechowywać dane pikselowe dla danych 8-bit-na kanał w kolejności BGRA. Jeśli więc chcesz dopasować format do danych w pikselach, aby szybciej przesyłać dane tekstur, chcesz użyć
GL_BGRA
dla format
, i GL_UNSIGNED_INT_8888
lub GL_UNSIGNED_BYTE
dla type
.
- w rzeczywistości nie będzie przechowywać 24-bitowych kolorów jako 24-bitowych. Zawsze będzie je uzupełniał do 32 bitów; alfa zostanie po prostu zignorowane podczas odczytu danych. Więc jeśli chcesz dopasować formatów, zawsze korzystać
GL_BGRA
format
z GL_RGB8
formatów graficznych, nawet jeśli trzeba umieścić dane manekina w składowej alfa.
Zasadniczo większość sprzętu nie obsługuje 3-komponentowych formatów tekstur, więc w tym konkretnym przykładzie możesz przyjąć dość bezpieczne założenie, że jest konwertowany. 3-komponentowa tekstura OpenGL jest właściwie 4-komponentowa sprzętowo, ale z komponentem alfa zignorowanym / ustawionym na 255 / cokolwiek.
https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (Ta strona „typowych błędów” jest kopalnią złota - dodaj ją teraz do zakładek!)
W bardziej ogólnym przypadku wydajność glTexSubImage2D może dać dobre wskazanie, czy przesyłanie musi przechodzić ścieżkę konwersji oprogramowania. Poradziłbyś sobie z tym podczas uruchamiania programu - po prostu utwórz pustą teksturę (za pomocą glTexImage2D z danymi NULL), a następnie wydaj kilka wywołań glTexSubImage2D, a po każdym z nich glFinish, aby upewnić się, że się zakończy. Zignoruj pierwszy, ponieważ konfigurowane są dla niego pamięci podręczne / stany / etc, a resztę czasu. Powtórz to dla kilku różnych formatów i wybierz najszybszy.
Inną alternatywą - widząc, jak otagowałeś to pytanie „Windows” - jest utworzenie urządzenia D3D podczas uruchamiania (zaraz po utworzeniu okna, ale przed uruchomieniem OpenGL), a następnie użycie D3D do sprawdzenia obsługi formatu. Podczas gdy OpenGL pozwala na konwersję oprogramowania do prawidłowego formatu wewnętrznego, D3D tego nie robi - jeśli nie jest obsługiwany przez sprzęt, nie możesz tego zrobić. Następnie zniszcz D3D i uruchom OpenGL. (Tej techniki można także użyć do zapytania o inne rzeczy, których OpenGL nie pozwala na bezpośrednie zapytania).
Przydatna jest praktyczna zasada, aby sprawdzić, co robisz w OpenGL z dokumentacją D3D. Jeśli D3D nie może czegoś zrobić, może to być dobry znak, że dana rzecz nie jest obsługiwana sprzętowo. Nie zawsze prawda, ale przydatne miejsce startowe.
źródło