glPushMatrix() glPopMatrix() GL_DEPTH_TEST

本文深入探讨了OpenGL中的glPushMatrix()、glPopMatrix()函数用于局部变换,以及GL_DEPTH_TEST如何实现深度测试,确保3D场景中元素的正确遮挡关系。通过实例说明了如何在不影响全局效果的情况下进行局部变换,并解释了深度测试的重要性。

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

glPushMatrix();  //这个就是把当前的矩阵数据压栈(就是保存起来),
glPopMatrix();  // 这个相反是出栈,就是把保存的再回复。

举个例子

你使用glScale()缩放了整个场景的东西,但你想其中某些东西要旋转,你就在要旋转的那个东西绘制前要加glRotate吧,可是你这样会影响到后边的所有东西,这时候你就可以在要旋转的东西前后分别加上glPushMatrix(); 和glPopMatrix();。这样的话对要旋转的那部分的操作就不会影响其他的东西了。


GL_DEPTH_TEST启动深度测试有什么用?
启动深度测试就是说深度(z值)会影响图形的遮挡关系(外边的会挡住里边的),不启动的话就是后画的挡住先画的(z值不起作用)

from OpenGL.GL import * from OpenGL.GLUT import * from OpenGL.GLU import * import math import time # 行星数据初始化 (同上) def draw_sphere(radius, slices, stacks): quad = gluNewQuadric() gluQuadricNormals(quad, GLU_SMOOTH) gluSphere(quad, radius, slices, stacks) gluDeleteQuadric(quad) def draw_orbit(a, e, i): glBegin(GL_LINE_LOOP) glColor3f(0.5, 0.5, 0.5) # 灰色轨道 for theta in range(0, 360, 5): rad = math.radians(theta) r = a * (1 - e**2) / (1 + e * math.cos(rad)) x = r * math.cos(rad) * DISTANCE_SCALE y = r * math.sin(rad) * math.sin(math.radians(i)) * DISTANCE_SCALE z = r * math.sin(rad) * math.cos(math.radians(i)) * DISTANCE_SCALE glVertex3f(x, y, z) glEnd() def draw_planet(name, time): data = planet_data[name] size = planet_sizes[name] * SIZE_SCALE # 计算位置 M = 2 * math.pi * time / data['T'] E = M # 近似处理 r = data['a'] * (1 - data['e']*math.cos(E)) * DISTANCE_SCALE x = r * math.cos(E) y = r * math.sin(E) * math.sin(math.radians(data['i'])) z = r * math.sin(E) * math.cos(math.radians(data['i'])) glPushMatrix() glTranslatef(x, y, z) # 设置行星颜色 if name == 'Earth': glColor3f(0.0, 0.0, 1.0) elif name == 'Mars': glColor3f(1.0, 0.0, 0.0) # ... 其他行星颜色设置 draw_sphere(size, 20, 20) glPopMatrix() def display(): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glLoadIdentity() # 设置相机位置 gluLookAt(0, -50, 30, 0, 0, 0, 0, 0, 1) # 绘制太阳 glColor3f(1.0, 1.0, 0.0) draw_sphere(planet_sizes['Sun'] * SIZE_SCALE, 30, 30) # 绘制轨道 for name in planet_data: draw_orbit(planet_data[name]['a'], planet_data[name]['e'], planet_data[name]['i']) # 绘制行星 current_time = time.time() - start_time for name in planet_data: draw_planet(name, current_time / TIME_SCALE) glutSwapBuffers() def animate(value): glutPostRedisplay() glutTimerFunc(30, animate, 0) # 初始化OpenGL glutInit() glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) glutInitWindowSize(1200, 900) glutCreateWindow(b"Solar System Animation") glEnable(GL_DEPTH_TEST) # 设置光照 glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glLightfv(GL_LIGHT0, GL_POSITION, [0, 0, 0, 1]) glLightfv(GL_LIGHT0, GL_DIFFUSE, [1, 1, 1, 1]) glutDisplayFunc(display) start_time = time.time() glutTimerFunc(0, animate, 0) glutMainLoop() 用上面的代码生成视频
最新发布
08-07
一.任务描述 1.本关任务 2.预期输出 3.具体要求 二.相关知识 一.任务描述 根据提示,在右侧修改代码,并自己绘制出图形。平台会对你编写的代码进行测试。 1.本关任务 了解简单实体构建的过程; 熟悉视点观察函数的设置和使用; 熟悉3D图形变换的设置和使用; 进一步熟悉基本3D图元的绘制。 2.预期输出 3.具体要求 (1).背景色为黑色,用 glclearcolor 来完成; (2).以中心为绘制原点,构建一个三棱锥; (3).创建二维数组用来存取三棱锥顶点坐标,顶点坐标分别为{-1,0,1},{1,0,1},{0,0,-0.7},{0,1.7,0}; (4).创建二维数组用来存取三棱锥面的颜色,分别为{0,1,0},{1,0,0},{1,1,0},{0,0,1} ; (5).创建二维数组用来存取三棱锥顶点的序号; (6).运用glPushMatrix()函数和glPopMatrix()函数进行矩阵操作,沿Z轴负方向平移-3.0f,沿Y轴方向平移0.2f,然后将三棱锥绕X轴方向选择95度 二.相关知识 为了完成本关任务,你需要掌握:二维数组的运用、实体平移和旋转、简单实体构建的操作。 // 提示:在合适的地方修改或添加代码 #include <GL/freeglut.h> #include<stdio.h> #include<iostream> // 评测代码所用头文件-开始 #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> using namespace std; // 评测代码所用头文件-结束 // 请在此添加你的代码 /********** Begin ********/ GLfloat points1[4][3] = { }; GLfloat Colors1[4][3] = { }; int vertice1[4][3] = { }; /********** End **********/ void InitGL(GLvoid) { glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glEnable(GL_COLOR_MATERIAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); } void Create() //创建三棱锥 { glBegin(GL_TRIANGLES); for (int i = 0; i < 4; i++) { glColor3fv(Colors1[i]); for (int j = 0; j < 3; j++) { int VtxId = vertice1[i][j]; glVertex3fv(points1[VtxId]); } } glEnd(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // 请在此添加你的代码 /********** Begin ********/ /********** End **********/ Create(); //三棱锥 glPopMatrix(); glutSwapBuffers(); } void reshape(int width, int height) { if (height == 0) height = 1; glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); glMatrixMod
03-28
#include <GL/glut.h> #include<math.h> using namespace std; #define PI 3.14159265354 GLfloat CIRCLE = 1.2f; GLfloat CIRCLE2 = 1.0f; int point = 720; GLfloat z = -5.0f; //用于记录平移距离 void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH); } void Reshape(GLsizei w, GLsizei h) { //重置窗口大小 glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(60.0, 1.0 * (GLfloat)w / (GLfloat)h, 1.0, 30.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -3.6); } // 显示函数,采用堆栈的方式 void display() { glClearColor(1, 1, 1, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); // 设置单位矩阵 glTranslatef(0.0f, 0.0f, z); glLoadIdentity(); glRotatef(1, 1.0f, 0.0f, 0.0f); double angle1 = 2 * PI / point; glPushMatrix(); // 绘制蓝色圆环 glColor4f(0, 0, 1, 0.7); glTranslatef(-2.4f, 1.0f, z); double angle2 = 0.0; glBegin(GL_LINE_STRIP); for (int i = 0; i <= point; i++) { angle2 += angle1;//每次循环加一度 glVertex2d(CIRCLE * cos(angle2), CIRCLE * sin(angle2));//利用三角函数定位每次绘画的点的位置 glVertex2d(CIRCLE2 * cos(angle2), CIRCLE2 * sin(angle2)); } glEnd(); glPopMatrix(); glPushMatrix(); // 补充黄色圆环 glColor4f(1, 0.7, 0, 0.9); glTranslatef(-1.2f, 0.0f, z); angle2 = 0.0; glBegin(GL_LINE_STRIP); for (int i = 0; i <= point; i++) { angle2 += angle1;//每次循环加一度,共进行60次循环,实现绘画一个60度的扇形的效果 glVertex2d(CIRCLE * cos(angle2), CIRCLE * sin(angle2)); glVertex2d(CIRCLE2 * cos(angle2), CIRCLE2 * sin(angle2)); } glEnd(); glPopMatrix(); glPushMatrix(); //绘制黑色圆环 glTranslatef(0.1f, 1.0f, z); glColor4f(0, 0, 0, 0.7); angle2 = 0.0; glBegin(GL_LINE_STRIP); for (int i = 0; i <= point; i++) { angle2 += angle1;//每次循环加一度 glVertex2d(CIRCLE * cos(angle2), CIRCLE * sin(angle2)); glVertex2d(CIRCLE2 *
03-19
#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
1.本关任务 实现Bezier曲面算法。通过调用drawBezierSurface函数生成Bezier曲面。 2.输入 (1)补全drawBezierSurface()函数。// 提示:在合适的地方修改或添加代码 #include <GL/freeglut.h> #include<stdio.h> #include <stdlib.h> #include <vector> // 评测代码所用头文件-开始 #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> // 评测代码所用头文件-结束 GLfloat ctrlpoints[4][4][3] = { {{-1.5, -1.5, 4.0}, {-0.5, -1.5, 2.0}, {0.5, -1.5, -1.0}, {1.5, -1.5, 2.0}}, {{-1.5, -0.5, 1.0}, {-0.5, -0.5, 3.0}, {0.5, -0.5, 0.0}, {1.5, -0.5, -1.0}}, {{-1.5, 0.5, 4.0}, {-0.5, 0.5, 0.0}, {0.5, 0.5, 3.0}, {1.5, 0.5, 4.0}}, {{-1.5, 1.5, -2.0}, {-0.5, 1.5, -2.0}, {0.5, 1.5, 0.0}, {1.5, 1.5, -1.0}} }; int u = 30, v = 8; //分别代表两个方向的离散取值。 void drawBezierSurface() { // 请在此添加你的代码 /********** Begin ********/ /********** End **********/ } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glPushMatrix(); glRotatef(85.0, 1.0, 1.0, 1.0); // Call the function to draw Bezier surface drawBezierSurface(); glPopMatrix(); glFlush(); } void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_FLAT); } void reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-4.0, 4.0, -4.0 * (GLfloat) h / (GLfloat) w, 4.0 * (GLfloat) h / (GLfloat) w, -4.0, 4.0); else glOrtho(-4.0 * (GLfloat) w / (GLfloat) h, 4.0 * (GLfloat) w / (GLfloat) h, -4.0, 4.0, -4.0, 4.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize (400, 400); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoopEvent(); /*************以下为评测代码,与本次实验内容无关,请勿修改**************/ GLubyte* pPixelData = (GLubyte*)malloc(400 * 400 * 3);//分配内存 GLint viewport[4] = { 0 }; glReadBuffer(GL_FRONT); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glGetIntegerv(GL_VIEWPORT, viewport); glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3], GL_RGB, GL_UNSIGNED_BYTE, pPixelData); cv::Mat img; std::vector<cv::Mat> imgPlanes; img.create(400, 400, CV_8UC3); cv::split(img, imgPlanes); for (int i = 0; i < 400; i++) { unsigned char* plane0Ptr = imgPlanes[0].ptr<unsigned char>(i); unsigned char* plane1Ptr = imgPlanes[1].ptr<unsigned char>(i); unsigned char* plane2Ptr = imgPlanes[2].ptr<unsigned char>(i); for (int j = 0; j < 400; j++) { int k = 3 * (i * 400 + j); plane2Ptr[j] = pPixelData[k]; plane1Ptr[j] = pPixelData[k + 1]; plane0Ptr[j] = pPixelData[k + 2]; } } cv::merge(imgPlanes, img); cv::flip(img, img, 0); cv::namedWindow("openglGrab"); cv::imshow("openglGrab", img); //cv::waitKey(); cv::imwrite("../img_step4/test.jpg", img); return 0; }补全代码
05-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值