将位图数据加载到 OpenGL 纹理中时出现问题

Posted

技术标签:

【中文标题】将位图数据加载到 OpenGL 纹理中时出现问题【英文标题】:Problems loading bitmap data into an OpenGL texture 【发布时间】:2013-05-06 13:53:46 【问题描述】:

不幸的是,glBindTexture() 有一些问题。

当我尝试将位图图像绑定到我的天空盒时,我只看到一些白色。我用其他数字对其进行了测试,但也不起作用。我确定问题出在 Engine 类中。

这是我的engine.cpp,我在这里加载位图等等:

#include <windows.h>
#include <gl/GL.h>

#include <iostream>
#include "engine.h"

unsigned char* Engine::getImageContents(char path[], BITMAPINFOHEADER* bih) 
    FILE* input; fopen_s(&input, path, "rb");

    if (input != NULL) 
        BITMAPFILEHEADER bfh;
        fread(&bfh, sizeof(bfh), 1, input);
        fread(&bih, sizeof(bih), 1, input);

        unsigned char* data =
            new unsigned char[bih->biWidth * bih->biHeight * bih->biBitCount / 8];

        fread(data, sizeof(data), 1, input);
        fclose(input);

        return data;
     else 
        return NULL;
    


void Engine::bindTexture(char path[]) 
    this->bindTexture(this->getTextureId(path));


void Engine::bindTexture(unsigned int id) 
    if (id != this->boundTexture) 
        glBindTexture(GL_TEXTURE_2D, id);
        this->boundTexture = id;
    


unsigned int Engine::getTextureId(char path[]) 
    if (this->textureMap.find(path) != this->textureMap.end()) 
        return this->textureMap[path];
     else 
        unsigned int id; glGenTextures(1, &id);
        BITMAPINFOHEADER bih;
        unsigned char* data = this->getImageContents(path, &bih);
        this->setupTexture(data, id, bih.biWidth, bih.biHeight);
        this->textureMap.insert(std::pair<char*, unsigned int>(path, id));
        return id;
    


void Engine::setupTexture(unsigned char* data, unsigned int id, long width, long height) 
    this->setupTexture(data, id, width, height, false);


void Engine::setupTexture(unsigned char* data, unsigned int id, long width, long height, bool clamp) 
    std::cout << height << std::endl;
    this->bindTexture(id);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp ? GL_CLAMP : GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp ? GL_CLAMP : GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT, data);

我使用这样的类:

Engine::bindTexture(path);

有什么想法吗?

【问题讨论】:

你确定图片的类型是GL_UNSIGNED_INT而不是GL_UNSIGNED_BYTE 你也不应该在glBindTexture之前做glActiveTexture(GL_TEXTURE0)吗? OpenGL 有 8 个纹理“槽”。 @rwols 我将 GL_UNSIGNED_INT 更改为 GL_UNSIGNED_BYTE 没有成功,并且找不到 glActiveTexture(GL_TEXTURE0)。 你在使用着色器吗?如果是这样,您的片段着色器是什么样的? @rwols 不,我没有 :) 【参考方案1】:

这是不对的:

fread(&bih, sizeof(bih), 1, input);

bih 已经是指向该结构的指针。你想要:

fread(bih, sizeof *bih, 1, input);

此外,您确实应该使用BITMAPFILEHEADER 中的bfOffBits,而不是假定位图位紧跟BITMAPINFOHEADER。见the MSDN topic describing the format of bitmap files。

【讨论】:

啊,老'sizeof(pointer)-while-I-actually-meant-sizeof(theByteArray)陷阱 @rwols:存储数据的地址也错误。大小确实与缓冲区匹配——但它们都是错误的。 我不认为这是一个问题,它没有任何改变。 @RandomUser 仅仅因为它没有解决您的所有错误并不意味着它实际上不是一个错误。【参考方案2】:

我发现一些可能的问题。

    您确定加载的是未压缩的 .bmp 文件,请检查 bfh.biCompression 如果bih->biBitCount == 32,你可以使用GL_RGBA,尝试使用GL_RGB 尝试使用 GL_UNSIGNED_BYTE 而不是 GL_UNSIGNED_INT 请检查图像大小,我认为天空盒应该是 128x128、256x256、512x512,即 2 次幂纹理大小 替换 fread(data, sizeof(data), 1, input); on fread(data, 1, bih->biWidth * bih->biHeight * bih->biBitCount / 8, 输入);

【讨论】:

我忘了说,当我得到 BITMAPINFOHEADER 的 bih.biWidth 时,它会返回一个随机值。我已经做到了第 3 点。我也将 GL_RGBA 更改为 GL_RGB 请更改 fread(&bih, sizeof(bih), 1, input);在 fread(&bih, sizeof(BITMAPINFOHEADER), 1, 输入); bih 是指针 @VladislavLitunovsky:不,您仍在传递指针的地址,这将破坏堆栈。请参阅我的答案以获取正确的呼叫。 @RandomUser 请看看这个link。它解释了如何加载 .bmp 和一些问题。 @VladislavLitunovsky 谢谢 :)

以上是关于将位图数据加载到 OpenGL 纹理中时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

c++:如何使用 sdl 将位图加载到 opengl 中的多维数据集中?

“位图太大,无法上传到纹理中”

如何在OpenGL中反转纹理颜色

Android 上的 OpenGL - 将位图转换为纹理,并保存纹理

OpenGL 七 - OpenGL 纹理基础与案例演示

如何在 C++ 中将位图绘制为 OpenGL 纹理?