1

看来我加载图像错误。图像看起来很混乱。我在这里做错了什么?

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
    glLoadIdentity();   // Reset The Current Modelview Matrix

    glEnable(GL_TEXTURE_2D);
    GLuint texture = 0;
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glBindTexture(GL_TEXTURE_2D, texture);

    FIBITMAP* bitmap = FreeImage_Load(FreeImage_GetFileType("C:/Untitled.bmp", 0), "C:/Untitled.bmp", BMP_DEFAULT);
    FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap);
    int nWidth = FreeImage_GetWidth(pImage);
    int nHeight = FreeImage_GetHeight(pImage);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));
    FreeImage_Unload(pImage);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f);
    glEnd();

    RECT desktop;
    const HWND hDesktop = GetDesktopWindow();
    GetWindowRect(hDesktop, &desktop);
    long horizontal = desktop.right;
    long vertical = desktop.bottom;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glDisable(GL_TEXTURE_2D);
    return TRUE;    // Keep Going
}

我在程序运行时看到的 程序运行时我看到的 内容 我在程序运行时看到的内容(我正在加载的位图) 我期望看到的

4

2 回答 2

3

这里的部分问题似乎是您从 FreeImage 获得的像素数据格式与glTexImage2D.

FreeImage_ConvertTo32Bits将返回具有 32 位像素数据的图像。我没有使用过 FreeImage,但通常这意味着每个像素都有 4 个 8 位分量,分别代表红色、绿色、蓝色和 alpha(不透明度)。从 BMP 文件中获得的数据格式取决于文件,其中可能有也可能没有 Alpha 通道。FreeImage_ConvertTo32Bits但是,如果您的原始图像完全不透明(或者因为您的 BMP 文件格式缺少 alpha 通道,或者因为您在创建文件时将其设置为不透明),那么假设将返回 alpha 设置为 255 的数据似乎是安全的。

这一切都很好,但问题在于调用glTexImage2D. 这个函数可以获取许多不同格式的像素数据。它用于解释数据的格式由参数确定,type如此format所述format您的代码中的值为GL_RGB. 这表示每个像素都有三个分量来描述其在像素数据中按顺序出现的红色、绿色和蓝色分量。type( )的值GL_UNSIGNED_BYTE表示每个组件的大小都是一个字节。问题是缺少 alpha 通道,因此glTexImage2D从错误的位置读取像素数据。正如 Roger Rowland 所指出的,FreeImage 产生的颜色顺序似乎是蓝-绿-红。解决方法很简单:设置formatGL_BGRA讲述glTexImage2Dalpha 分量和数据的顺序:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nWidth, nHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));

要查看此问题是否可以解释奇怪的输出,请考虑原始图像中的蓝色大块。根据 GIMP,这主要是蓝色和少量绿色(R=0,G=162,B=232)。所以我们有这样的事情:

B G R A B G R A B G R A ...   meaning of bytes from FreeImage_GetBits
1 - 0 1 1 - 0 1 1 - 0 1 ...   "values" of bytes (0 -> 0, - -> 162, 1 -> 232 or 255)
R G B R G B R G B R G B ...   what glTexImage2D thinks the bytes mean

这里的纹理像素颜色是:橙色、浅黄色、亮青色和紫色。这些重复是因为读取 4 个像素消耗 12 个字节,这正好等于原始像素的 3 个。这解释了您在大部分输出图像上看到的模式。(最初我使用 RGBA 顺序完成了此操作,但 GBRA 版本更适合图像 - 差异在行的开头特别明显)。

但是我必须承认我不确定一开始发生了什么以及如何将它与粉红色方块联系起来!所以这里可能还有其他问题,但希望使用GL_BGRA将是朝着正确方向迈出的一步。

于 2013-11-30T11:37:05.960 回答
2

您正在制作 32 bpp 图像,因此您需要有正确的纹理声明:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight,
    0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)FreeImage_GetBits(pImage));

此外,该FreeImage_GetBits函数返回通常对齐的数据,以便每行以 4 字节边界结束。因此,如果您的图像是 32 bpp(与您的一样),或者如果您的图像宽度是 2 的幂,则可以,否则,您需要适当地设置解包对齐方式。

于 2013-11-30T14:09:09.720 回答