OpenGLut开发入门系列教程2:显示一个基本空白窗口

系列教程索引:OpenGLut开发入门系列教程索引

上一篇:OpenGL开发入门系列教程2:hello world

确认库可以正常加载后就可以进行界面的开发了。

flow

如图为OpenGL界面开发的基本流程。那么我们需要init/display/reshape/key处理函数,但是不是全都要,比如说没有键盘控制处理就不需要key函数了。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <iostream>

#include <GL/glut.h>
#include <GL/gl.h>
#include <unistd.h>

using namespace std;

//esc键
#define ESCAPE 27

int window;//glut窗口标识

void init(){
glClearColor(1.0f,0.0f,1.0f,0.0f);//红绿蓝alpha值
glShadeModel(GL_SMOOTH);//色彩绘制模式
}

void display(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(1.0f,1.0f,-6.0f);

glBegin(GL_TRIANGLES);//图像绘制部分
glEnd();

glFlush();//刷新缓冲区
}

// 窗口大小变化回调函数
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, static_cast<GLdouble>(w/h), 0.1, 100000.0);//设置长宽视景
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

//键盘回调函数
void keyboard(unsigned char key,int x,int y){
usleep(100);

if(key == ESCAPE){
glutDestroyWindow(window);//销毁窗口
exit(0);
}
}

int main(int argc, const char * argv[]) {
// 初始化显示模式
glutInit(&argc, const_cast<char **>(argv));
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

// 初始化窗口
glutInitWindowSize(500, 500);//初始界面大小
glutInitWindowPosition(100, 100);//界面初始位置
window=glutCreateWindow(argv[0]);//创建界面,界面标题为argv[0],即程序名称

init();//opengl初始化
glutReshapeFunc(&reshape);
glutDisplayFunc(&display);//回调函数
glutKeyboardFunc(&keyboard);//键盘回调函数

// 开始主循环绘制
glutMainLoop();
return 0;
}

测试输出为:

plain

调整init()函数中的:

1
glClearColor(1.0f,0.0f,1.0f,0.0f);//红绿蓝alpha值

就可以调整界面背景色(具体描述见函数说明系列)。

gl开头的是OpenGL的基本函数,glut是控制界面显示的部分。也就是说,可以换成glx(x窗口)、Qt等等。

我们来借glut输出OpenGL库版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <GL/glut.h>
#include <stdio.h>

int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(300, 300);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL Version");

const GLubyte *name = glGetString(GL_VENDOR); //返回负责当前OpenGL实现厂商的名字
const GLubyte *flag = glGetString(GL_RENDERER); //返回一个渲染器标识符,通常是个硬件平台
const GLubyte *OpenGLVersion = glGetString(GL_VERSION); //返回当前OpenGL实现的版本号
const GLubyte *gluVersion = gluGetString(GLU_VERSION); //返回当前GLU工具库版本

printf("OpenGL实现厂商的名字:%s\n", name);
printf("渲染器标识符:%s\n", flag);
printf("OpenGL实现的版本号:%s\n", OpenGLVersion);
printf("OGLU工具库版本:%s\n", gluVersion);
return 0;
}

实体机输出为:

1
2
3
4
OpenGL实现厂商的名字:NVIDIA Corporation
渲染器标识符:GeForce GTX 1660 Ti/PCIe/SSE2
OpenGL实现的版本号:4.6.0 NVIDIA 455.38
OGLU工具库版本:1.3

在虚拟机下面为:

1
2
3
4
OpenGL实现厂商的名字:VMware, Inc.
渲染器标识符:SVGA3D; build: RELEASE; LLVM;
OpenGL实现的版本号:2.1 Mesa 20.0.8
OGLU工具库版本:1.3

只有gl库是不会输出数据的,只有二次开发的库中厂商才会写入这些数据。

OpenGL规定了一系列函数,具体实现由显卡或者其他厂商实现。

OpenGLut代码模板

由最基本的窗口代码,我们从中提取出一个通用的开发代码模板。本系列的后续所有文章附属代码都是在此模板上修改的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
///
/// \note 功能:OpenGL+GLUT开发代码模板
///

#include <iostream>

#include <GL/glut.h>
#include <GL/gl.h>
#include <unistd.h>//延时

using namespace std;

#define ESCAPE 27//esc键ASCII码值

int window; //glut窗口标识号

//初始化函数,设置所有初始化值
void initGL(int width, int height)
{
glClearColor(1.0f, 1.0f, 0.0f, 0.0f); //将界面背景清空为红绿蓝alpha值对应的颜色
glClearDepth(1.0);//设置清空深度缓冲区(depth buffer)
glDepthFunc(GL_LESS);//设置深度测试的类型
glEnable(GL_DEPTH_TEST);//设置进行深度测试(depth test)
glShadeModel(GL_SMOOTH);//栅格化模式为平滑,只有平滑和两种模式

glMatrixMode(GL_PROJECTION);//矩阵模式为投影模式
glLoadIdentity();//重置投影矩阵

gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);//计算窗口的显示比例

glMatrixMode(GL_MODELVIEW);//
}

//OpenGL的主要绘图函数,绘制什么显示什么。
void displayGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//清空界面和depth缓冲区
glLoadIdentity();//调整视场
////////////////下面是实际的绘图函数///////////////////

////////////////绘图函数结束/////////////////////////
//双缓冲技术,交换缓冲区以显示刚刚绘制的图像
glutSwapBuffers();
}

// 窗口大小变化回调函数
void reshapeGL(int w, int h)
{
glViewport(0, 0, w, max(h,1));//重置当前窗口的视场和角度,防止出现长度为0的情况,尤其是下面还将h用作除数
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, static_cast<GLfloat>(w/h),0.1f,100.0f); //设置长宽视景
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

//如果有按键按下调用此函数
void keyboard(unsigned char key, int x, int y)
{
usleep(100);//稍微延时以免干扰

if (key == ESCAPE)//如果是escape键
{
glutDestroyWindow(window); //销毁窗口
exit(0);//正常退出程序
}
}

int main(int argc,char **argv)
{
//初始化glut状态,并且接管所有传给程序的参数
glutInit(&argc, argv);
//设置显示模式:双缓冲、RGBA颜色、alpha支持、depth缓冲支持
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);

// 初始化窗口
glutInitWindowSize(640, 480); //初始界面大小
glutInitWindowPosition(100, 100); //界面初始位置,相对于屏幕左上角的像素值
//创建界面,界面标题为argv[0],即程序名称,也可以以字符串进行指定
//同时获取创建的窗口ID号,销毁时使用
window = glutCreateWindow(argv[0]);

glutIdleFunc(&displayGL);//即使没有任何事件,也重绘场景
glutReshapeFunc(&reshapeGL);//注册调整窗口大小回调函数
glutDisplayFunc(&displayGL);//注册主要绘图回调函数
glutKeyboardFunc(&keyboard);//注册键盘回调函数

initGL(640,480);//初始化窗口

glutMainLoop();//开始事件处理引擎

return 0;
}

完整源码在OpenGL_Freshman下的OpenGLut的2中。

下一篇:OpenGL开发入门系列教程3:基本图形