OpenGL学习笔记(一):环境搭建、三维空间坐标系理解以及OpenGL的基本使用

原博主博客地址: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》下载地址:

   

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



















发布了255 篇原创文章 · 获赞 365 · 访问量 50万+

猜你喜欢

转载自blog.csdn.net/qq21497936/article/details/78660326