OPenGL笔记

您所在的位置:网站首页 一点透视图立方体 OPenGL笔记

OPenGL笔记

2023-06-16 17:13| 来源: 网络整理| 查看: 265

一、前置知识

经过前面的学习,我们已经知道了立方体怎么创建了,接下来学习怎么给立方体贴图;

为了将纹理正确的映射到四边形上,您必须:

将纹理的​​右上角​​​ 映射到四边形的​​右上角​​ ;

纹理的​​左上角​​​ 映射到四边形的​​左上角​​ ;

纹理的​​右下角​​​ 映射到四边形的​​右下角​​ ;

纹理的​​左下角​​​ 映射到四边形的​​左下角​​ ;

如果映射错误的话,图像显示时可能上下 颠倒,侧向一边或者什么都不是

​​glTexCoord2f(x, y)​​:

第一个参数是X坐标;0.0 是纹理的左侧、0.5 是纹理的中点、 1.0 是纹理的右侧;

第二个参数是Y坐标;0.0 是纹理的底部、 0.5 是纹理的中点、1.0 是纹理的顶部;

二、效果展示

 

 

 

三、完整代码 #ifndef GL_TEST_H #define GL_TEST_H #include //因为QGLWidget类被包含在qgl.h头文件中 #include //使用glut库中的API #include #include //继承QGLWidget得到OPenGL窗口部件类 class GL_Test : public QGLWidget { public: GL_Test(QWidget* parent = 0, bool fs = false); ~GL_Test(); protected: /************************************************************************************************* QGLWidget 类已经内置了对 OpenGL 的处理,就是通过对 initializeGL()、 paintGL()和 resizeGL()这个三个函数实现 *************************************************************************************************/ void initializeGL() override; //用来初始化OPenGL窗口,可以在里面设定一些有关选项 void paintGL() override; //用来绘制OPenGL的窗口,只要有更新发生,这个函数就会被调用 void resizeGL(int w, int h) override; //用来处理窗口大小变换这一事件,resizeGL()在处理完后会自动刷新屏幕 void keyPressEvent(QKeyEvent* e) override; //Qt键盘事件处理函数 void loadGLTextures(); //载入指定的图片并生成相应的纹理 protected: bool fullscreen; //用来保存窗口是否处于全屏状态的变量 GLfloat xRot, yRot, zRot; //用来处理立方体的旋转 GLuint texture[1]; //用来存储纹理(长度为1的数组) }; #endif // GL_TEST_H #include "gl_test.h" GL_Test::GL_Test(QWidget* parent, bool fs) : QGLWidget(parent) { fullscreen = fs; xRot = 0.0; yRot = 0.0; zRot = 0.0; setGeometry(500,500,640,480); //设置窗口大小、位置 setWindowTitle("The first OpenGL Window"); //设置窗口标题 if(fullscreen) { showFullScreen(); } QTimer* timer = new QTimer(this); connect(timer,&QTimer::timeout,[=]{ updateGL(); }); timer->start(50); } GL_Test::~GL_Test() { } void GL_Test::initializeGL() { loadGLTextures(); //载入纹理 glEnable(GL_TEXTURE_2D); //启用纹理 glShadeModel(GL_SMOOTH); //启用smooth shading(阴影平滑) glClearColor(0.0, 0.0, 0.0, 0.5); //清除屏幕时所用的颜色,rgba【0.0(最黑)~1.0(最亮)】 glClearDepth(1.0); //设置深度缓存 glEnable(GL_DEPTH_TEST); //启动深度测试 glDepthFunc(GL_LEQUAL); //所作深度测试的类型 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //真正精细的透视修正,告诉OPenGL我们希望进行最好的透视修正,这会十分轻微的影响性能,但使得透视图看起来好一点 } void GL_Test::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存 //----------------------------------------- glLoadIdentity(); //重置当前的模型观察矩阵 glTranslatef(0.0, 0.0, -5.0); glRotatef(xRot, 1.0, 0.0, 0.0); //绕X轴旋转xRot度 glRotatef(yRot, 0.0, 1.0, 0.0); //绕X轴旋转yRot度 glRotatef(zRot, 0.0, 0.0, 1.0); //绕X轴旋转zRot度 //选择我们使用的纹理 glBindTexture(GL_TEXTURE_2D, texture[0]); //如果您在您的场景中使用多个纹理,您应该使用来 glBindTexture(GL_TEXTURE_2D, texture[所使用纹理对应的数字]) 选择要绑定的纹理; //当您想改变纹理时,应该绑定新的纹理。并且您不能在glBegin()和glEnd()之间绑定纹理,必须在glBegin()之前或glEnd()之后绑定; //绘制正方形开始 glBegin(GL_QUADS); //前面 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 ); //后面 glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 ); glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 ); glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 ); //顶面 glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 ); glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 ); glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 ); glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 ); //底面 glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, -1.0, -1.0 ); glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, -1.0, -1.0 ); glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 ); //右面 glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 ); glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 ); glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 ); //左面 glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 ); glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 ); glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 ); glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 ); glEnd(); //绘制正方形结束 //----------------------------------------- xRot += 2; yRot += 3; zRot += 4; } void GL_Test::resizeGL(int w, int h) { if(h == 0) { //防止h为0 h = 1; } glViewport(0, 0, (GLint)w, (GLint)h); //重置当前的视口(Viewport) glMatrixMode(GL_PROJECTION); //选择投影矩阵 glLoadIdentity(); //重置投影矩阵 gluPerspective( 45.0, (GLfloat)w/(GLfloat)h, 0.1, 100.0 ); //建立透视投影矩阵 glMatrixMode(GL_MODELVIEW); //选择模型观察矩阵 glLoadIdentity(); //重置模型观察矩阵 } void GL_Test::keyPressEvent(QKeyEvent* e) { switch (e->key()) { case Qt::Key_Q: { fullscreen = !fullscreen; if(fullscreen) { showFullScreen(); }else { showNormal(); setGeometry(500,500,640,480); } updateGL(); break; }//case Qt::Key_Q case Qt::Key_Escape: { close(); }//Qt::Key_Escape }//switch (e->key()) } void GL_Test::loadGLTextures() { QImage tex,buf; if(!buf.load(":/Images/1591561503-gB5rD.jpg")) { //用QImage类载入纹理图片 QImage dummy(128,128,QImage::Format_RGB32); //如果载入不成功,生成一个128*128的32位色的绿色图片 dummy.fill(Qt::green); buf = dummy; } tex = QGLWidget::convertToGLFormat(buf); //QGLWidget的静态函数,专门用来转换图片 glGenTextures(1,&texture[0]); //创建一个纹理 glBindTexture(GL_TEXTURE_2D,texture[0]); //使用来自位图数据生成的典型纹理 /*告诉OPenGL将纹理名字texture[0]绑定到纹理目标上;2D纹理只有高度(在Y轴上)和宽度(在X轴上)*/ //真正的创建纹理 //GL_TEXTURE_2D:告诉 OpenGL 此纹理是一个 2D 纹理; //数字0:代表图像的详细程度; //数字3:是数据的成分数; //tex.width():是纹理的宽度 //tex.height():是纹理的高度; //GL_RGBA:告诉 OpenGL 图像数据由红、绿、蓝三色数据以及 alpha 通道数据组成; //GL_UNSIGNED_BYTE:意味着组成图像的数据是无符号字节类型的; //tex.bits():告诉 OpenGL 纹理数据的来源; glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits()); //告诉 OpenGL 在显示图像时,当它比放大得原始的纹理大(GL_TEXTURE_MAG_FILTER)或缩小得比原始得纹理小(GL_TEXTURE_MIN_FILTER)时, //OpenGL 采用的滤波方式 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //我们都采用 GL_LINEAR,这使得纹理从很远处到离屏幕很近时都平滑显示; //使用 GL_LINEAR 需要 CPU 和显卡做更多的运算,如果您的机器很慢,您也许应该采用 GL_NEAREST; //过滤的纹理在放大的时候,看起来斑驳的很,您也可以结合这两种滤波方式: 在近处时使用 GL_LINEAR,远处时 GL_NEAREST; }

附、给立方体每个面渲染不同的纹理

Qt学习基地:C/C++项目实战/Qt5/C语言/c++/数据库/OpenCV/MFC/QT项目-学习视频教程-腾讯课堂

1、创建多个纹理

void GL_Test::loadGLTextures() { QStringList Images; Images


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3