原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78660326
《OpenGL学习笔记》系列博客目录地址:http://blog.csdn.net/qq21497936/article/category/7315532
OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用
前话
经常看到技术需求当中有opengl,所以有时间就介绍并学习下opengl,opengl对于qt来说只是窗口不一样,其调用的实际函数都是opengl的原生函数,所以这可以说学会opengl是完全意义上的一通百通。
Qt for OpenGL
Qt5.2 OpenGL 下载地址:
《OpenGL编程指南(原书第8版)中文高清版.pdf》下载地址:
http://download.csdn.net/download/qq21497936/10137423
Demo
源码下载地址: http://download.csdn.net/download/qq21497936/10136743
OpenGL坐标系理解
在OpenGL里面移动坐标是相对于当前点开始移动的相对坐标;
在OpenGL里面绕轴变换,每次画图形之前会设置一个变换原点,变换的轴必须通过该点,所以要实现理想的变换,必须很好的掌握此相对于变换图形的“原点”(非整体坐标系原点)。
OpenGL基本窗口建立
安装完成后,新建一个Qt QGui程序,使用QWdiget做为基类,声明自己的窗口类(OpenGL显示窗口),如下图:
创建完成后,首先就是要该窗口继承的基类QWidget改为QGLWidget。
在工程文件.pro加入:
QT += opengl
头文件加入,特别注意包含GL/glu,否则调用glu函数会没有
#include <QGLWidget> #include <GL/glu.h> // 必须包含,否则glu相关函数无法使用
重载三个函数
protected: void initializeGL(); // 用来初始化 void paintGL(); // 用来绘制,更新发生,就会被调用 void resizeGL(int width, int height); // 窗口大小变化时,会调用
至此Qt OpenGL基本的程序窗口搭建完毕,不论任何语言的opengl的使用,除了之前创建窗口不同之外,以下opengl学习调用的函数为opengl的原生函数。
OpenGL基本使用
初始化窗口代码
void NeHeWidget::initializeGL() // 每次paintgGL()或resizeGL()之前会自动调用 { // 启用smooth shading(阴影平滑) glShadeModel(GL_SMOOTH); // 设置清楚屏幕所用的颜色 色彩值范1围从0.0-1.0 (R G B A) 清屏时A不起作用 glClearColor(0.1, 0.1, 0.4, 1.0); /* 以下三行必须做,是关于深度缓存的,深度缓存是OpenGL十分重要的部分*/ // 设置深度缓存 glClearDepth(1.0); // 启用深度测试 glEnable(GL_DEPTH_TEST); // 设置深度测试的类型 glDepthFunc(GL_LEQUAL); // 设置希望得到最好的透视修正 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); }
画一个三角形和一个四边形,填充颜色,并让三角形饶Y轴变换,四边形绕X轴变换
void NeHeWidget::paintGL() { // 清除屏幕和深度缓存 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 重置观察矩阵/投影矩阵 // (X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外) // OpenGL屏幕中心的坐标值是X和Y轴上的0.0点 // 中心左面的坐标值是负值,右面是正值。 // 移向屏幕顶端是正值,移向屏幕底端是负值。 // 移入屏幕深处是负值,移出屏幕则是正值。 glLoadIdentity(); // 沿着X、Y、Z轴移动 // X轴左移1.5个单位,Y轴不动(0.0),最后移入屏幕6.0个单位 // 注意在glTranslatef(x, y, z)中当您移动的时候, // 您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置 glTranslatef(-1.5, 0.0, -6.0); // 让对象绕某个轴旋转 绕 Y 轴旋转三角形 glRotatef(rTri, 0.0, 1.0, 0.0); 注意:X轴旋转,X,Y,Z可调整绕哪个轴 // glBegin(GL_TRIANGLES)开始绘制三角 // 以目前所在的点为画图原点(0,0,0) 开始相对原点坐标画三角形 glBegin(GL_TRIANGLES); glColor3f( 1.0, 0.0, 0.0 ); // 红色 颜色+顶点 glVertex3f( 0.0, 1.0, 0.0); // 中上顶点 红色+中上 glColor3f( 0.0, 1.0, 0.0 ); // 绿色 glVertex3f(-1.0, -1.0, 0.0 ); // 左下顶点 绿色+左下 glColor3f( 0.0, 0.0, 1.0 ); // 蓝色 glVertex3f( 1.0, -1.0, 0.0 ); // 右下顶点 蓝色+右下 // glEnd()告诉OpenGL图形(三角)已经创建好了 // 三点间自动使用渐变填充 glEnd(); // 重置模型观察矩阵 重置模型观察矩阵之后,X、Y、Z轴都以复位 glLoadIdentity(); glTranslatef( 1.5, 0.0, -6.0 ); // 移动到点 // 绕 X 轴旋转四边形 注意:X轴旋转,X,Y,Z可调整绕哪个轴 glRotatef(rQuad, 1.0, 0.0, 0.0); // 绘制四边形 // 以目前所在的点为画图原点(0,0,0) 开始相对原点坐标画四边形 glBegin( GL_QUADS ); glColor3f( 0.5, 0.5, 1.0 ); // 蓝色,下面画的点都是蓝色直到换颜色后换点 glVertex3f(-1.0, 1.0, 0.0 ); // 左上顶点 glVertex3f( 1.0, 1.0, 0.0 ); // 右上定点 glVertex3f( 1.0, -1.0, 0.0 ); // 右下定点 glVertex3f(-1.0, -1.0, 0.0 ); // 坐下定点 glEnd(); }
每当窗口做大小改变的时候,我们需要resizeGL整个窗口大小
void NeHeWidget::resizeGL(int width, int height) { // 防止height为0 if(height == 0) { height = 1; } // 重置当前的视口 glViewport(0, 0, (GLint)width, (GLint)height); // 选择投影矩阵 glMatrixMode(GL_PROJECTION); // 重置观察矩阵/投影矩阵 当调用次函数,实际将当前点移到了屏幕中心 glLoadIdentity(); // 建立透视投影矩阵,需要<GL/glu.h>头文件 gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 ); // 选择模型观察矩阵 glMatrixMode( GL_MODELVIEW ); // 重置观察矩阵/投影矩阵 glLoadIdentity(); }
最后我们需要不断的定时修改旋转角度,修改后需要刷新,定义定时器
_pTimer = new QTimer(this); _pTimer->setInterval(10); connect(_pTimer, SIGNAL(timeout()), this, SLOT(slotRotate())); _pTimer->start();
定时器函数,可使用startTimer函数来使用窗口自带的timerEvent定时事件
void NeHeWidget::slotRotate() { rTri+=1; // 增加三脚形Y轴角度 rQuad+=1; // 增加四边形X轴角度 update(); // 刷新 }
扩展
使三角形绕非标准轴运动
… // 绕 X 轴旋转四边形 glRotatef(rQuad, 1.0, 0.0, 0.0); …
修改后
// 使其绕XZ平面45°轴运动,该轴通过该图形初始化原点… … glRotatef(rQuad, 1.0, 0.0, 1.0); …
关于图形初始化原点,是开始画图形之前设置的相对原点,以此点为0,0,0为坐标开始画图形,具体代码如下,glTranslatef后的glBegin和glEnd之间所花的图形,其旋转变换轴必须通过glTranslatef的相对原点
// 清除屏幕和深度缓存 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 重置观察矩阵/投影矩阵 // (X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外) // OpenGL屏幕中心的坐标值是X和Y轴上的0.0点 // 中心左面的坐标值是负值,右面是正值。 // 移向屏幕顶端是正值,移向屏幕底端是负值。 // 移入屏幕深处是负值,移出屏幕则是正值。 glLoadIdentity();glLoadIdentity(); // 沿着X、Y、Z轴移动 // X轴左移1.5个单位,Y轴不动(0.0),最后移入屏幕6.0个单位 // 注意在glTranslatef(x, y, z)中当您移动的时候, // 您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置 glTranslatef(-1.5, 0.0, -6.0); // 让对象绕某个轴旋转 绕 Y 轴旋转三角形 glRotatef(rTri, 1.0, 1.0, 0.0); // glBegin(GL_TRIANGLES)开始绘制三角 // 以目前所在的点为画图原点(0,0,0) 开始相对原点坐标画三角形 glBegin(GL_TRIANGLES); glColor3f( 1.0, 0.0, 0.0 ); // 红色 // 颜色+顶点 glVertex3f( 0.0, 1.0, 0.0); // 中上顶点 红色+中上 glColor3f( 0.0, 1.0, 0.0 ); // 绿色 glVertex3f(-1.0, -1.0, 0.0 ); // 左下顶点 绿色+左下 glColor3f( 0.0, 0.0, 1.0 ); // 蓝色 glVertex3f( 1.0, -1.0, 0.0 ); // 右下顶点 蓝色+右下 // glEnd()告诉OpenGL图形(三角)已经创建好了 // 三点间自动使用渐变填充 glEnd();
使三角形绕非标准轴运动
… //使其绕XY平面45°轴运动,该轴通过该图形初始化原点 glTranslatef( 1.5, 0.0, -6.0 ); // 移动到点 // 绕 X 轴旋转四边形 glRotatef(rQuad, 1.0, 1.0, 0.0); …
修改后
… //使其绕XZ平面45°轴运动,该轴通过该图形初始化原点 glTranslatef( 1.5, 0.0, -6.0 ); // 移动到点 // 绕 X 轴旋转四边形 glRotatef(rQuad, 1.0, 0.0, 0.0); …
原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/78660326