Как загрузить текстуры в OpenGL с помощью библиотеки FreeImage?

Я изучаю OpenGL на C++, используя учебники NeHe, но я пытаюсь сделать их с помощью библиотеки FreeImage, а не Glaux или SOIL. Хороший момент, который я вижу в использовании FreeImage, - это последнее обновление в октябре прошлого года, в то время как почва не обновлялась в течение 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(bitmap)* на *FreeImage_GetBits (bitmap)*, я получу segfault.

что я делаю не так?

2 ответов


есть две проблемы с вашим кодом-одна из них заключается в том, что вы конвертируете изображение в 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-internal. Где каждая линия развертки обычно выравнивается по границе 4 байта. Это будет работать нормально, пока у вас есть Power-of-two текстуры. Однако для текстур NPOT вам нужно будет указать правильное выравнивание распаковки для OpenGL.

в FreeImage есть еще одна функция, которая позволит вам получить несогласованный плотно упакованный массив пиксели:FreeImage_ConvertToRawBits()