如何使用 FreeImage 库将纹理加载到 OpenGL?

Posted

技术标签:

【中文标题】如何使用 FreeImage 库将纹理加载到 OpenGL?【英文标题】:How do I load textures to OpenGL using FreeImage library? 【发布时间】:2013-06-15 16:48:44 【问题描述】:

我正在使用 NeHe 教程在 C++ 中学习 OpenGL,但我正在尝试使用 FreeImage 库而不是 Glaux 或 SOIL 来完成它们。我看到使用 FreeImage 的好处是它的最后一次更新是在去年 10 月,而 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(bitmap)* 更改为 *FreeImage_GetBits(bitmap)* 我得到一个段错误。

我做错了什么?

【问题讨论】:

【参考方案1】:

您的代码有两个问题 - 一个是您将图像转换为 32 位,但您为 openGL (GL_RGB) 指定了 24 位纹理格式。第二个是您将 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);

【讨论】:

由于扫描线对齐要求,这不适用于所有图像。 @SergeyK。对于 32 位像素,所有扫描线大小无论如何都是 4 字节对齐的。在什么情况下你认为它不起作用?【参考方案2】:

扩展上一个答案:

FreeImage_GetBits() 函数将返回指向以 FreeImage 内部格式存储的数据的指针。其中每条扫描线通常与 4 字节边界对齐。当您拥有二次幂纹理时,这将正常工作。但是,对于 NPOT 纹理,您需要为 OpenGL 指定正确的解包对齐方式。

FreeImage 中还有另一个函数可以让您获得未对齐的紧密排列的像素数组:FreeImage_ConvertToRawBits()

【讨论】:

以上是关于如何使用 FreeImage 库将纹理加载到 OpenGL?的主要内容,如果未能解决你的问题,请参考以下文章

基于OpenGL编写一个简易的2D渲染框架-04 绘制图片

如何将 UV 纹理从搅拌机加载到 opengl android java

如何使用 libgdx 资产管理器正确加载纹理

如何在 1D 缓冲区中生成 2D 纹理并将其加载到 OpenGL 中?

如何使用threejs将fabricjs加载为obj的纹理

FreeImage 生成带透明通道的GIF