OpenGL(九)——Qt OpenGL创建一个OpenGL的窗口

20 篇文章 68 订阅
13 篇文章 49 订阅

OpenGL(九)——Qt OpenGL创建一个OpenGL的窗口

一、NeHe教程

OpenGL(八)——Qt OpenGL实现一个旋转的正方体,上一篇介绍了在Qt的OpenGL实现一个旋转的多边形,是以前学习Qt下OpenGL,参考的NeHe的教程实现的,所以,接下来还是把之前学习的NeHe教程也一起贴出来吧,与小伙伴们一起分享、交流。

二、Qt下创建一个OpenGL的窗口

在之前的文章中介绍了Qt中封装的OpenGL接口:Qt 中编写OpenGL

QGLWidget和QOpenGLWidget提供了三个方便的虚拟函数,可以在子类中重写这些函数来执行典型的OpenGL任务。

paintGL():渲染OpenGL场景。每当需要更新小部件时调用。
resizeGL ():设置OpenGL视区、投影等。每当小部件调整了大小时都会调用
该视区(并且当它第一次显示时也会调用,因为所有新创建的小部件都会自动获
得一个调整大小的事件)。
initializeGL():设置OpenGL呈现上下文,定义显示列表等。在第一次调
用resizeGL ()或paintGL ()之前调用一次。

所以创建一个OpenGL的项目,首先就是实现这三个重载的函数。

三、代码

头文件

#include <QObject>
#include <QWidget>
//#include <QGLWidget>
#include <qgl.h>

/*
*创建一个OpenGL的窗口.
*/

class NeHe_1_Widget : public QGLWidget
{
    Q_OBJECT
public:
    NeHe_1_Widget(QWidget *parent = 0);
    ~NeHe_1_Widget();

protected:
    void initializeGL(); //是用来初始化这个OpenGL窗口部件的,可以在里面设定一些有关选项.
    void paintGL();      //是用来绘制OpenGL的窗口了,只要有更新发生,这个函数就会被调用.
    void resizeGL( int width, int height ); //就是用来处理窗口大小变化这一事件的
,width和height就是新的大小状态下的宽和高了,另外resizeGL()在处理完后会自动刷新屏幕。

};

cpp文件:

#include "nehe_2_widget.h"
#include <GL/glu.h>

NeHe_2_Widget::NeHe_2_Widget(QWidget *parent):QGLWidget(parent)
{
    setGeometry(0,0, 640, 480);
}

NeHe_2_Widget::~NeHe_2_Widget()
{

}

void NeHe_2_Widget::initializeGL()
{
    glShadeModel( GL_SMOOTH );
    //这一行启用smooth shading(阴影平滑)。阴影平滑通过多边形精细的混合色彩,并对外部光进行平滑。我将在另一个教程中更详细的解释阴影平滑。

    glClearColor( 0.0, 0.0, 0.0, 0.0 );
    //这一行设置清除屏幕时所用的颜色。如果您对色彩的工作原理不清楚的话,我快速解释一下。色彩值的范围从0.0到1.0。0.0代表最黑的情况,1.0就 \
    是最亮的情况。glClearColor后的第一个参数是红色,第二个是绿色,第三个是蓝色。最大值也是1.0,代表特定颜色分量的最亮情况。最后一个参数是 \
    Alpha值。当它用来清除屏幕的时候,我们不用关心第四个数字。现在让它为0.0。我会用另一个教程来解释这个参数。\
       通过混合三种原色(红、绿、蓝),您可以得到不同的色彩。希望您在学校里学过这些。因此,当您使用glClearColor(0.0, 0.0, 1.0, 0.0 ),\
    您将用亮蓝色来清除屏幕。如果您用glClearColor(0.5, 0.0, 0.0, 0.0 )的话,您将使用中红色来清除屏幕。不是最亮(1.0),也不是最暗 (0.0)。\
    要得到白色背景,您应该将所有的颜色设成最亮(1.0)。要黑色背景的话,您该将所有的颜色设为最暗(0.0)。

    glClearDepth( 1.0 );
    //设置深度缓存。

    glEnable( GL_DEPTH_TEST );
    //启用深度测试。

    glDepthFunc( GL_LEQUAL );
    //所作深度测试的类型。

    //上面这三行必须做的是关于depth buffer(深度缓存)的。将深度缓存设想为屏幕后面的层。深度缓存不断的对物体进入屏幕内部有多深进行跟踪。\
    我们本节的程序其实没有真正使用深度缓存,但几乎所有在屏幕上显示3D场景OpenGL程序都使用深度缓存。它的排序决定那个物体先画。这样您就不会将\
    一个圆形后面的正方形画到圆形上来。深度缓存是OpenGL十分重要的部分。

    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
    //真正精细的透视修正。这一行告诉OpenGL我们希望进行最好的透视修正。这会十分轻微的影响性能。但使得透视图看起来好一点。
}
glMatrixMode(GL_PROJECTION)指明接下来的两行代码将影响projection matrix(投影矩阵)。投影矩阵负责为我们的场景增加透视。 glLoadIdentity()近似于重置。它将所选的矩阵状态恢复成其原始状态。调用glLoadIdentity()之后我们为场景设置透视图。 

* glMatrixMode(GL_MODELVIEW)指明任何新的变换将会影响 modelview matrix(模型观察矩阵)。模型观察矩阵中存放了我们的物体讯息。最后我们重置模型观察矩阵。
如果您还不能理解这些术语的含义,请别着急。在以后的教程里,我会向大家解释。只要知道如果您想获得一个精彩的透视场景的话,必须这么做。 

* 这个函数的作用是重新设置OpenGL场景的大小,而不管窗口的大小是否已经改变(假定您没有使用全屏模式)。甚至您无法改变窗口的大小时(例如您在全屏模式下),它至少仍将运行一次——在程序开始时设置我们的透视图。OpenGL场景的尺寸将被设置成它显示时所在窗口的大小。
void NeHe_1_Widget::resizeGL( int width, int height )
{
    if ( height == 0 )
    {
      height = 1;
    }
    //防止height为0。

    glViewport( 0, 0, (GLint)width, (GLint)height );
    //重置当前的视口(Viewport)。

    glMatrixMode( GL_PROJECTION );
    //选择投影矩阵。

    glLoadIdentity();
    //重置投影矩阵。

    gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );
    //建立透视投影矩阵。

    glMatrixMode( GL_MODELVIEW );
    //选择模型观察矩阵。

    glLoadIdentity();
    //重置模型观察矩阵。

    //上面几行为透视图设置屏幕。意味着越远的东西看起来越小。这么做创建了一个现实外观的场景。\
    此处透视按照基于窗口宽度和高度的45度视角来计算。0.1,100.0是我们在场景中所能绘制深度的起点和终点。
}
/**这个函数中包括了所有的绘图代码。任何您所想在屏幕上显示的东东都将在此段代码中出现。以后的每个教程中我都会在例程的此处增加新的代码。
*如果您对OpenGL已经有所了解的话,您可以在 glLoadIdentity()调用之后,函数返回之前,试着添加一些OpenGL代码来创建基本的形。
*如果您是OpenGL新手,等着我的下个教程。目前我们所作的全部就是将屏幕清除成我们前面所决定的颜色,清除深度缓存并且重置场景。我们仍没有绘制任何东东。*/
void NeHe_1_Widget::paintGL()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    //清楚屏幕和深度缓存。
    glLoadIdentity();
    //重置当前的模型观察矩阵。
}

四、运行结果

运行一下这个类,看一下结果。

 因为没有绘制任何内容,所以看起来就是上面这个。 

上一篇:OpenGL(八)——Qt OpenGL实现一个旋转的正方体

下一篇:OpenGL(十)——Qt OpenGL绘制多边形

本文原创作者:冯一川(ifeng12358@163.com),未经作者授权同意,请勿转载。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冯一川

谢谢老板对我的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值