使用 Glut 和 C 时扭曲的纹理
Posted
技术标签:
【中文标题】使用 Glut 和 C 时扭曲的纹理【英文标题】:Distorted Texture when using Glut and C 【发布时间】:2017-10-17 08:01:23 【问题描述】:我正在努力让自己熟悉 XCode 9 中的 GLUT 框架,以便在未来的项目中进行工作,但现在我无法让纹理正确显示。
所以我的目标是将此 bmp 图像显示为纹理:
到这个红色方块所在的位置:
结果是这样的:
什么时候应该是这样的:
这是我用于初始化纹理的代码。
GLuint loadAndBufferImage(const char * filename)
GLuint texture;
unsigned char header[54];
unsigned int dataPos;
unsigned int width, height;
unsigned int imageSize;
unsigned char * data;
FILE * file = fopen(filename, "rb");
if(!file)printf("Image could not load\n"); exit(2);
if(fread(header, 1, 54, file) != 54)
printf("Not a correct BMP file.\n");
return -1;
if(header[0] != 'B' || header[1] != 'M')
printf("Not a correct BMP file.\n");
return -1;
dataPos = *(int*)&(header[0x0A]);
imageSize = *(int*)&(header[0x22]);
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
if(imageSize == 0) imageSize = width * height * 4;
if(dataPos==0) dataPos=54;
data = malloc(imageSize);
if(!data)printf("No more memory\n"); exit(1);
fread(data, 1, imageSize, file);
fclose(file);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
free(data);
return texture;
这就是调用该函数的地方。
GameWindow *initializeGameWindow()
GameWindow *gw = malloc(sizeof(*gw));
if(gw == NULL)
printf("Error: no more memory");
exit(1);
gw->render = render;
gw->update = update;
gw->isRunning = isRunning;
gw->setRunning = setRunning;
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glViewport(0.0f, 0.0f, _width, _height);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, _width, 0, _height);
glMatrixMode(GL_MODELVIEW);
glGenBuffers(1, &_vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(VertexData), (GLvoid *)offsetof(VertexData, pos));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(VertexData), (GLvoid *)offsetof(VertexData, tex));
_textureBufferID = loadAndBufferImage("test.bmp");
return gw;
我要猜测一下,这与我如何从图像中获取数据以及可能的纹理参数有关。如果是这样,那么我该如何解决这个问题?否则我还需要做些什么来设置纹理吗?
编辑:
所以我按照建议在纹理初始化代码中的fread(data, 1, imageSize, file);
上方添加了fseek(file, (long)dataPos, SEEK_SET);
,与初始结果相比,它似乎稍微改变了图像。
我还尝试将 GL_RGBA 和 GL_BGRA 分别更改为 glTexImage2D 函数中的 GL_RGB 和 GL_BGR 并且发生了这种情况。
编辑 2: 所以经过一些研究和实验后,发现另一个问题是因为当我将图像保存为位图时,图像被设置为 indexed color mode 而不是 RGB color mode文件。 (我正在使用 Gimp 编辑器。)它一定影响了数据的存储方式,因为当我比较它们时,文件像素数据部分中的十六进制值和总文件大小不同。但在编辑器中将其切换为 RBG 颜色模式是解决此问题的最后关键。
https://image.ibb.co/fC99Lm/Screen_Shot_2017_10_18_at_4_15_36_AM.png
感谢您的所有帮助。
资源:
https://en.wikipedia.org/wiki/BMP_file_format
http://fac.ksu.edu.sa/sites/default/files/lab08_6.pdf
【问题讨论】:
您确定 BMP 文件中有 Alpha 通道数据吗?您将数据作为 RGBA 传递给纹理(我的意思是调用glTexImage2D
)。
我尝试按照建议更改 glTexImage2D 函数(分别更改为 GL_RGB 和 GL_BGR)并发布了结果。我认为颜色数据的长度是 4 个字节而不是 3 个。
【参考方案1】:
您已阅读但忽略了dataPos
,图像数据的偏移量。使用
fseek(file, (long)dataPos, SEEK_SET);
fread(data, 1, imageSize, file);
将文件指针定位到数据。其原因是,标题和图像数据之间可以存在调色板数据。
【讨论】:
我只是按照您的建议进行了尝试,与最初的结果相比,它似乎稍微改变了图像。 我建议你阅读一下BMP file format。这很复杂。在BITMAPINFOHEADER
中是偏移量0x1C
(有时称为WORD biBitCount
)的2 字节字段,它给出了每个像素的位数。您可以通过将文件大小与图像尺寸乘以 3 或乘以 4 进行比较来粗略评估。以上是关于使用 Glut 和 C 时扭曲的纹理的主要内容,如果未能解决你的问题,请参考以下文章