OpenGL 的小试验(三)

0

Comments

screenshot-opengl今天回家本想在我的 Ubuntu 上玩玩 OpenGL,结果花了一个下午,终于研究出些东西了……

在 NeHe 的源代码中似乎有 Linux 的,不过一个是用 glut、一个是用 SDL、一个是用 GLX,原本看到 glut 是 OpenGL 官方的一个夸平台的简单窗口系统,结果发现全屏不能……于是就找到了 GLFW 这个东西,据说比较简单,不过还是研究了一个下午。

下面说一下研究成果吧,首先,想要用 g++ 编译用 GLFW 写的程序,一定要加这些编译参数: -lglfw -lGL -lGLU -lXrandr,特别是最后一个,是其官方参考中没有的!这个是我查了许多资料,然后瞎猜猜到的……再说说头文件,这次不需要引用3个库了,只有一个 #include <GL/glfw.h> 就可以了,似乎把其他的库自动引用了。另外就是,画完要用 glfwSwapBuffers(); 刷新,不然不仅什么都不会显示,而且还会死机……除此之外,还要注意那个键盘的按键,不要想当然的和 Windows 下拿去类比,根据研究发现,键盘事件交出的 key 最大可以达到 318,而且特殊键都会以这些“大值”返回,所以一定要申请好内存……

这次主要参考了:
GLFW Reference
OpenGL Tutorials – Basics
以及 NeHe 的 OpenGL 教程。

这个例子是一个转动的彩色四棱锥,只有 ESC 和 F11 的键盘处理,附加帧数计算。

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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <GL/glfw.h>
 
bool fullscreen;
bool active = true;
bool keys[GLFW_KEY_LAST+1]; // 为键盘按键申请空间
 
GLfloat rtri;
 
bool initGLFW(const char*, int, int);
 
// 帧数统计用
double starttime;
int flames = 0;
 
// 绘制代码
void drawGLScene()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
 
	glTranslatef(0.0f, 0.0f, -5.0f);
	glRotatef(rtri, 0.0f, 1.0f, 0.0f);
	glBegin(GL_TRIANGLES);
		glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 0.0f,  1.0f,  0.0f);
		glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
		glColor3f(0.0f, 0.0f, 1.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
 
		glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 0.0f,  1.0f,  0.0f);
		glColor3f(0.0f, 0.0f, 1.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
		glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
 
		glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 0.0f,  1.0f,  0.0f);
		glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
		glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
 
		glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( 0.0f,  1.0f,  0.0f);
		glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
		glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
	glEnd();
 
	++flames;
	double dt = glfwGetTime() - starttime;
	if (dt >= 5.0f)
	{
		printf("%d frames in %.1lf seconds = %.3lf FPSn", flames, dt, double(flames) / dt);
		flames = 0;
		st = glfwGetTime();
	}
 
	rtri += 0.15f;
}
 
// 键盘处理
void keyPress(int key, int action)
{
	keys[key] = action;
 
	if (keys[GLFW_KEY_ESC])
	{
		active = false;
		return;
	}
 
	if (keys[GLFW_KEY_F11])
	{
		keys[GLFW_KEY_F11] = GLFW_RELEASE;
		glfwTerminate();
		fullscreen = ! fullscreen;
		initGLFW("Upsuper's OpenGL Test", 640, 480);
	}
}
 
inline void quit(int status)
{
	glfwTerminate();
	exit(status);
}
 
inline void quit() {
	quit(0);
}
 
inline void report_error(const char* info)
{
	puts(info);
	quit(1);
}
 
void resizeGLScene(int width, int height)
{
	if (height <= 0) height = 1;
 
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
 
	gluPerspective(45.0f, GLfloat(width)/GLfloat(height), 0.1f, 100.0f);
 
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
 
bool initGL(int width, int height)
{
	glShadeModel(GL_SMOOTH);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	return true;
}
 
bool initGLFW(const char* title, int width, int height)
{
	glfwInit();
	if (! glfwOpenWindow(width, height, 8, 8, 8, 8, 24, 0, 
			fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW))
		report_error("ERROR: Cannot open a window.");
	glfwSetWindowTitle(title);
	glfwEnable(GLFW_AUTO_POLL_EVENTS);
	glfwSetKeyCallback(keyPress);
	glfwSetWindowSizeCallback(resizeGLScene);
 
	initGL(width, height);
}
 
int main(int argc, char** argv)
{
	printf("Would you like to run in fullscreen mode? [Y/n]");
	int c = getchar();
	fullscreen = (c != 'n' && c != 'N');
 
	memset(keys, false, sizeof(keys));
	initGLFW("Upsuper's OpenGL Test", 640, 480);
 
	st = glfwGetTime();
	do
	{
		drawGLScene();
		glfwSwapBuffers();
	}
	while (active);
 
	quit();
	return 0;
}

代码比 VC++ 的那个短好多,再次证明 Linux 是多么适用于编程……

同时根据帧数对比,印证了我的猜想——全屏下比较流畅!我这里全屏下 fps 达到了窗口模式的接近3倍。

附 makefile 文件(这也是我第一次写 makefile):

1
2
all: test1.cpp a.cpp
	g++ test1.cpp -o test1 -lglfw -lGL -lGLU -lXrandr

最后,我还是十分高兴,那个绘制代码是我自己写出来的,不是抄的了!(虽然以前写过……)

写 OpenGL 就是爽……

Leave a Reply