LOADBMP (RGB) 模式

本文介绍了一个用于从BMP文件加载图像并将其转换为OpenGL纹理的C/C++函数。该函数首先检查文件名是否有效,然后尝试打开文件,并利用auxDIBImageLoad函数加载图像数据。接着创建内部纹理,并在完成操作后释放图像资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UINT LoadBMP(char * FileName)
{
UINT texture = 0;

if(!FileName)
return NULL;

AUX_RGBImageRec *pImage;

FILE *pFile = fopen(FileName, "rb");

if(!pFile)
return NULL;

pImage = auxDIBImageLoad(FileName);

if(!pImage)
{
return NULL;
}

texture = GenerateInternalTexture(pImage->data, 3, pImage->sizeX, pImage->sizeY, GL_RGB);

if (pImage)
{
if (pImage->data)
{
free(pImage->data);
}

free(pImage);
}

return texture;
}

#include <glut.h> #include <GL/gl.h> #include <GL/glu.h> #include <stdio.h> #include <math.h> #include<iostream> #define GL_BGR 0x80E0 // 扩展的BGR颜色格式 #define M_PI 3.14159265358979323846 // 纹理ID GLuint skyTexture, roadTexture, wheelTexture, carTexture; // 小车位置和车轮旋转角度 float carPosition = -1.0f; float wheelRotation = 0.0f; // 改进的BMP文件加载函数 GLuint loadBMP(const char* filename) { FILE* file; errno_t error = fopen_s(&file, filename, "rb"); // 使用二进制模式打开文件 if (error != 0 || file == nullptr) { std::cerr << "无法打开文件: " << filename << std::endl; return 0; } // 读取BMP文件头 unsigned char header[54]; if (fread(header, 1, 54, file) != 54) { std::cerr << "无效的BMP文件头: " << filename << std::endl; fclose(file); return 0; } // 检查是否为BMP文件 if (header[0] != 'B' || header[1] != 'M') { std::cerr << "不是BMP文件: " << filename << std::endl; fclose(file); return 0; } // 获取图像数据的偏移量 int dataPos = *(int*)&(header[0x0A]); // 获取图像大小 int imageSize = *(int*)&(header[0x22]); // 获取图像宽度和高度 int width = *(int*)&(header[0x12]); int height = *(int*)&(header[0x16]); // 如果BMP文件没有提供图像大小,则计算它 if (imageSize == 0) imageSize = width * height * 3; // 3表示RGB // 如果数据位置未指定,则使用默认值 if (dataPos == 0) dataPos = 54; // BMP文件头的大小 // 为图像数据分配内存 unsigned char* data = new unsigned char[imageSize]; // 读取图像数据 fseek(file, dataPos, SEEK_SET); fread(data, 1, imageSize, file); fclose(file); // 创建纹理ID GLuint textureID; glGenTextures(1, &textureID); // 绑定纹理 glBindTexture(GL_TEXTURE_2D, textureID); // 加载纹理数据到OpenGL glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data); delete[] data; // 设置纹理过滤 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); return textureID; } // 绘制带纹理的矩形 void drawTexturedQuad(float x, float y, float width, float height) { glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(x, y); glTexCoord2f(1.0f, 0.0f); glVertex2f(x + width, y); glTexCoord2f(1.0f, 1.0f); glVertex2f(x + width, y + height); glTexCoord2f(0.0f, 1.0f); glVertex2f(x, y + height); glEnd(); } // 绘制带纹理的旋转车轮 void drawWheel(float cx, float cy, float radius) { glPushMatrix(); // 移动到车轮中心并应用旋转 glTranslatef(cx, cy, 0.0f); glRotatef(wheelRotation, 0.0f, 0.0f, 1.0f); const int segments = 36; glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0.5f, 0.5f); // 中心点 glVertex2f(0.0f, 0.0f); for (int i = 0; i <= segments; i++) { float angle = 2.0f * M_PI * i / segments; float x = cos(angle) * radius; float y = sin(angle) * radius; // 计算纹理坐标 glTexCoord2f(0.5f + 0.5f * cos(angle), 0.5f + 0.5f * sin(angle)); glVertex2f(x, y); } glEnd(); glPopMatrix(); } // 绘制小车 void drawCar() { // 车身 (矩形) glColor3f(1.0f, 1.0f, 1.0f); // 确保颜色为白色,不影响纹理颜色 glBindTexture(GL_TEXTURE_2D, carTexture); drawTexturedQuad(carPosition - 0.2f, -0.5f, 0.4f, 0.2f); // 车轮 glBindTexture(GL_TEXTURE_2D, wheelTexture); drawWheel(carPosition - 0.15f, -0.55f, 0.07f); // 左轮 drawWheel(carPosition + 0.15f, -0.55f, 0.07f); // 右轮 } // 场景渲染函数 void renderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 绘制天空 glBindTexture(GL_TEXTURE_2D, skyTexture); drawTexturedQuad(-1.0f, -1.0f, 2.0f, 2.0f); // 绘制道路 glBindTexture(GL_TEXTURE_2D, roadTexture); drawTexturedQuad(-1.0f, -1.0f, 2.0f, 0.5f); // 绘制小车 drawCar(); glutSwapBuffers(); } // 动画更新函数 void update(int value) { // 更新小车位置(水平移动) carPosition += 0.01f; if (carPosition > 1.2f) carPosition = -1.2f; // 更新车轮旋转角度(顺时针旋转) wheelRotation -= 5.0f; if (wheelRotation > 360.0f) wheelRotation += 360.0f; // 触发重绘 glutPostRedisplay(); glutTimerFunc(16, update, 0); // 约60FPS } // 初始化函数 void init() { // 设置清除颜色为白色(背景色) glClearColor(1.0, 1.0, 1.0, 0.0); // 加载纹理 skyTexture = loadBMP("sky.bmp"); roadTexture = loadBMP("road.bmp"); wheelTexture = loadBMP("wheel.bmp"); carTexture = loadBMP("car.bmp"); // 检查纹理是否加载成功 if (!skyTexture || !roadTexture || !wheelTexture || !carTexture) { std::cerr << "纹理加载失败!请确保所有BMP文件都在正确的位置。" << std::endl; } // 启用纹理和混合 glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // 设置2D正交投影 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(-1.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); // 设置背景色 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); } int main(int argc, char** argv) { // 初始化GLUT glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(800, 600); glutCreateWindow("OpenGL 2D动画 - 移动小车"); // 注册回调函数 init(); glutDisplayFunc(renderScene); glutTimerFunc(0, update, 0); // 启动动画 // 进入主循环 glutMainLoop(); return 0; } 开启光照计算,加入至少2个光源,并设置2种以上材质,使得场景中的对象呈现出不同的材质特征。
最新发布
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值