Я изучаю OpenGL на C ++, используя учебные пособия NeHe, но я пытаюсь сделать это с помощью библиотеки FreeImage вместо Glaux или SOIL. Хорошее замечание, которое я вижу в использовании FreeImage, заключается в том, что его последнее обновление было в октябре прошлого года, в то время как SOIL не обновлялся в течение 5 лет. Проблема в том, что я не могу правильно загрузить текстуры.
Вот мой код:
static GLuint texture = 0;
if (texture == 0)
{
FIBITMAP* bitmap = FreeImage_Load(
FreeImage_GetFileType("textures/test/nehe_06.png", 0),
"textures/test/nehe_06.png");
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
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, 3, FreeImage_GetWidth(bitmap), FreeImage_GetHeight(bitmap),
0, GL_RGB, GL_UNSIGNED_BYTE, FreeImage_ConvertTo32Bits(bitmap));
FreeImage_Unload(bitmap);
}
Используя этот код, полученная текстура неправильна: она черная, с цветными точками и полосами, и изменение изображения дает тот же результат, поэтому я предполагаю, что не загружаю текстуру правильно.
Я пытался поменять местами красные и синие биты (читай, что FreeImage загружается в BGR), но безрезультатнее. Наконец, если я изменяю * FreeImage_ConvertTo32Bits (растровое изображение) * на * FreeImage_GetBits (растровое изображение) *, я получаю ошибку сегмента.
Что я делаю не так?
С вашим кодом есть две проблемы — одна из них заключается в том, что вы конвертируете изображение в 32-битное, но вы указываете 24-битный формат текстуры для openGL (GL_RGB
). Во-вторых, вы передаете сам объект FreeImage в текстуру, а не в преобразованные биты.
Вам нужно сделать что-то подобное вместо этого
FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap);
int nWidth = FreeImage_GetWidth(pImage);
int nHeight = FreeImage_GetHeight(pImage);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight,
0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));
FreeImage_Unload(pImage);
Чтобы расширить предыдущий ответ:
FreeImage_GetBits()
Функция вернет указатель на данные, хранящиеся во внутреннем формате FreeImage. Где каждая линия сканирования обычно выровнена по границе 4 байта. Это будет хорошо работать, пока у вас есть власть двух текстур. Однако для текстур NPOT вам нужно будет указать правильное выравнивание распаковки для OpenGL.
В FreeImage есть еще одна функция, которая позволит вам получить невыровненный плотно упакованный массив пикселей: FreeImage_ConvertToRawBits()