glMatrixMode()函数的参数中GL_PROJECTION和GL_MODELVIEW和GL_TEXTURE的区别

本文详细介绍了OpenGL中的glMatrixMode函数及其参数GL_PROJECTION、GL_MODELVIEW和GL_TEXTURE的应用场景。通过实例说明如何在3D和2D绘图中切换不同的矩阵模式。

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

原文地址:http://blog.youkuaiyun.com/jiangdf/article/details/8460012

这两个都是glMatrixMode()函数的参数,那就先说说glMatrixMode吧~,这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项(参数)有,GL_PROJECTION,GL_MODELVIEW和GL_TEXTURE;


如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。这样,接下来的语句可以是跟透视相关的函数,比如glFrustum()或gluPerspective();
如果参数是GL_MODELVIEW,这个是对模型视景的操作,接下来的语句描绘一个以模型为基础的适应,这样来设置参数,接下来用到的就是像gluLookAt()这样的函数;
若是GL_TEXTURE,就是对纹理相关进行操作;

顺便说下,OpenGL里面的操作,很多是基于对矩阵的操作的,比如位移,旋转,缩放,所以,这里其实说的规范一点就是glMatrixMode是用来指定哪一个矩阵是当前矩阵,而它的参数代表要操作的目标,GL_PROJECTION是对投影矩阵操作,GL_MODELVIEW是对模型视景矩阵操作,GL_TEXTURE是对纹理矩阵进行随后的操作


切换当前矩阵.
如.要使用透视(3D).那么先要设置透视投影
glMatrixMode(GL_PROJECTION); //切换到投影矩阵.
//...设置透视投影
设置完成后开始画图,需要切换到 模型视图矩阵 才能正确画图.
glMatrixMode(GL_MODELVIEW);
// 画一个物体A (看起来是3D的),
// 如这时候需画一个 2D效果 的 物体A,那么又需要透视投影

glMatrixMode(GL_PROJECTION); //切换到投影矩阵..
// ..设置正交投影
//..设置完成,切换回模型视图矩阵.....
glMatrixMode(GL_MODELVIEW);
// 再画一个物体A (看起来是2D的)


// 如从头到尾都是画3D/2D, 只需初始化时设置一次.
// 如果有交替,那么就需要glMatrixMode() 切换
// 因这样设置很烦人,所以又有glPushMatrix() 保存当前矩阵

#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
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 glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(50, 1, 0, 10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Reset The Current Modelview Matrix gluLookAt(1, 1, 1, 0, 0, 0, 0, 1, 0); // 设置线宽 glLineWidth(2.0f); // 绘制 Y 轴(红色) glColor3f(1.0f, 0.0f, 0.0f); // 红色 glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); // 起点 glVertex3f(1.0f, 0.0f, 0.0f); // 终点 glEnd(); // 绘制 Y 轴负方向(红色) glColor3f(1.0f, 0.0f, 0.0f); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x00FF); glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); //起点 glVertex3f(-1.0f, 0.0f, 0.0f); //终点 glEnd(); glDisable(GL_LINE_STIPPLE); // 绘制 Z 轴(蓝色) glColor3f(0.0f, 0.0f, 1.0f); // 蓝色 glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); // 起点 glVertex3f(0.0f, 1.0f, 0.0f); // 终点 glEnd(); // 绘制 Z 轴负方向(蓝色) glColor3f(0.0f, 0.0f, 1.0f); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x00FF); glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); //起点 glVertex3f(0.0f, -1.0f, 0.0f); //终点 glEnd(); glDisable(GL_LINE_STIPPLE); // 绘制 X 轴(绿色) glColor3f(0.0f, 1.0f, 0.0f); // 绿色 glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); // 起点 glVertex3f(0.0f, 0.0f, 1.0f); // 终点 glEnd(); // 绘制 X 轴负方向(绿色) glColor3f(0.0f, 1.0f, 0.0f); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0x00FF); glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); //起点 glVertex3f(0.0f, 0.0f, -1.0f); //终点 glEnd(); glDisable(GL_LINE_STIPPLE); // 画旗面 glBegin(GL_QUADS); glColor3f(1.0f, 0.0f, 0.0f); // 红色 glVertex3f(0.0f, 0.0f, 0.0f); // 左下 glVertex3f(0.3f, 0.0f, 0.0f); // 右下 (x轴正方向) glVertex3f(0.3f, 0.0f, 0.2f); // 右上 (z轴正方向) glVertex3f(0.0f, 0.0f, 0.2f); // 左上 glEnd(); // 绘制五星(新增部分) glColor3f(1.0f, 1.0f, 0.0f); // 黄色 // 大星(位于左上1/4区域) drawStar(0.05f, 0.13f, 0.03f); // (x, z) = (3*0.5/3, 2*5/6) // 四颗小星(相对大星的位置) drawStar(0.1f, 0.15f, 0.01f); // 第一小星 drawStar(0.11f, 0.13f, 0.01f); // 第二小星 drawStar(0.09f, 0.10f, 0.01f); // 第三小星 drawStar(0.06f, 0.08f, 0.01f); // 第四小星 // 恢复默认颜色(白色) glColor3f(1.0f, 1.0f, 1.0f); return TRUE; // Keep Going }在这段函数内部增加代码,让xyz轴旁边标注上xyz
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值