OpenGL是图形硬件的一种软件接口。OpenGL的设计目标就是作为一种流线型的、独立于硬件的接口,可以在许多不同的硬件平台上实现。为了实现这个目标,OpenGL并未包含用于执行窗口任务或者获取输入之类的函数。反之,必须通过具体的窗口系统来控制OpenGL应用程序所使用的特定硬件。OpenGL也并没有提供用于描述三维物体模型的高级函数。在OpenGL中,程序员必须根据一些为数不多的基本几何图元(如点、直线和多边形)来创建所需要的模型。
OpenGL工具库(GLU)提供了许多建模功能,例如二次曲面以及NURBS曲线和曲面。GLU是所有OpenGL实现的一个标准组成部分。
OpenGL对场景中的图像进行渲染时所执行的主要操作为:
1、根据几何图元创建形状,从而建立物体的数学描述。(OpenGL把点、直线、多边形和位图作为基本的图元。)
2、在三维空间中排列物体,并选择观察符合场景的有利视角。
3、计算所有物体的颜色。颜色可以是由应用程序明确指定的,也可以是根据特定的光照条件所确定的,或者是通过纹理贴到物体的表面而获得的,或者是上述这三种操作的混合产物。
4、把物体的数学描述以及与物体相关的颜色信息转换为屏幕上的像素。这个过程称为光栅化(rasterization)。
GLUT, OpenGL实用工具库
OpenGL包含了许多渲染函数,但它们的设计目的是独立于任何窗口系统或操作系统。因此,它并没有包含打开窗口或者从键盘或鼠标读取事件的函数。GLUT可用来简化打开窗口、检测输入等任务。GLUT还包含了一些函数,用于创建一些更为复杂的三维物体,例如球体、圆环面和茶壶等。
窗口管理
GLUT通过5个函数执行初始化窗口所需要的任务:
- glutInit(int *argc, char **argv)对GLUT进行初始化,并处里所有的命令行参数(对于X系统,这将是类似 -display和-geometry的选项)。glutInit()应该在调用其他任何GLUT函数之前被调用。
- glutInitDisplayMode(unsigned int mode)指定了是使用RGBA模式还是颜色索引模式。另外还可以指定是使用单缓冲还是使用双缓冲窗口。如果使用颜色索引模式,就需要把一些颜色加载到颜色映射表中,这个任务可以用glutSetColor()来完成。最后,还可以使用这个函数来表示希望窗口拥有相关联的深度、模板、多重采样和/或累积缓冲区。
- glutInitWindowPosition(int x, int y)指定了窗口左上角的屏幕位置。
- glutInitWindowSize(int width, int height)指定了窗口的大小(以像素为单位)。
int glutCreateWindow(char *string)创建一个支持OpenGL渲染环境的窗口。这个函数返回一个唯一的标识符,标识了这个窗口。在调用glutMainLoop()函数之前,这个窗口并没有被显示。
显示回调函数
glutDisplayFunc(void (*func)(void))函数,每当GLUT确定一个窗口的内容需要重新显示时,通过glutDisplayFunc() 所注册的那个回调函数就会被执行。应次应该把重绘场景所需要的所有代码都放在这个显示回调函数里。
如果程序修改了窗口的内容,有时候可能需要调用glutPostRedisplay(),这个函数将会指示glutMainLoop()调用已注册的显示回调函数。
运行程序
最后,必须调用glutMainLoop()来启动程序。所有已经创建的窗口将会在这时显示,对这些窗口的渲染也开始生效。事件处理循环开始启动,已注册的显示回调函数被触发。一旦进入循环,它就永远不会退出。
OpenGL的Hello World
- #include <GL/glut.h>
- #define kWindowWidth 400
- #define kWindowHeight 300
- void initGL(void) {
- /* Select clearing (background) color */
- glClearColor(0.0, 0.0, 0.0, 0.0);
- /* Initialize viewing values */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
- }
- void DrawGLScene(void) {
- /* clear all pixel */
- glClear(GL_COLOR_BUFFER_BIT);
- /* draw white polygon (rectangle) with corners at
- * (0.25, 0.25, 0.0) and (0.75, 0.75, 0.0)
- */
- glColor3f(0, 0.5, 1.0);
- glBegin(GL_POLYGON);
- glVertex3f(0.25, 0.25, 0.0);
- glVertex3f(0.75, 0.25, 0.0);
- glVertex3f(0.75, 0.75, 0.0);
- glVertex3f(0.25, 0.75, 0.0);
- glEnd();
- /* don't wait
- * start processing buffered OpenGL routines
- */
- glFlush();
- }
- void ResizeGLScene(int width, int height) {
- }
- /*
- * Declare initial window size, position, and display mode
- * (single buffer and RGBA). Open window with "hello"
- * in its title bar. Call initialization routines.
- * Register callback function to display graphics.
- * Enter main loop and process events.
- */
- int main(int argc, char **argv) {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
- glutInitWindowSize(kWindowWidth, kWindowHeight);
- glutInitWindowPosition(100, 100);
- glutCreateWindow(argv[0]);
- initGL();
- glutDisplayFunc(DrawGLScene);
- glutReshapeFunc(ResizeGLScene);
- glutMainLoop();
- return 0;
- }
程序运行的前提当然为系统有OpenGL的一个实现,系统中存在GLUT library。Ubuntu上,编译时可使用如下的编译命令:
- $ g++ -lglut -o OpenGLTest01 main.cpp
处理输入事件可以使用下面这些函数注册一些回调函数,当指定的事件发生时,这些函数便会被调用:
- glutReshapeFunc(void (*func)(int w, int h))表示当窗口的大小发生改变时应该采取什么行动。
- glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))和glutMouseFunc(void (*func)(int button, int state, int x, int y))允许把键盘上的一个键或鼠标上的一个按钮与一个函数相关联,当这个键或按钮被按下或释放时,这个函数就会被调用。
- glutMotionFunc(void (*func)(int x, int y))注册了一个函数,当按下一个鼠标按钮移动鼠标时,这个函数就会被调用。
空闲处理
可以在glutIdleFunc(void (*func)(void))回调函数中指定一个函数,如果不存在其他尚未完成的事件,就执行这个函数。这个回调函数接受一个函数指针作为它的唯一参数。如果向它传递NULL(0),就相当于禁用这个函数。
动画 = 重绘 + 交换
- #include <GL/glut.h>
- #include <stdlib.h>
- #define kWindowWidth 400
- #define kWindowHeight 300
- static GLfloat spin = 0.0;
- void initGL(void) {
- /* Select clearing (background) color */
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glShadeModel(GL_FLAT);
- }
- void DrawGLScene(void) {
- /* clear all pixel */
- glClear(GL_COLOR_BUFFER_BIT);
- glPushMatrix();
- glRotatef(spin, 0.0, 0.0, 1.0);
- glColor3f(0, 0.5, 1.0);
- glRectf(-0.75, -0.75, 0.75, 0.75);
- glPopMatrix();
- glutSwapBuffers();
- }
- void spinDisplay(void) {
- spin = spin + 2.0;
- if(spin > 360.0)
- spin = spin - 360;
- glutPostRedisplay();
- }
- void ResizeGLScene(int width, int height) {
- glViewport(0, 0, (GLsizei) width, (GLsizei) height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-2.0, 2.0, -2.0, 2.0, -1.0, 1.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
- void mouse(int button, int state, int x, int y) {
- switch(button) {
- case GLUT_LEFT_BUTTON:
- if(state == GLUT_DOWN)
- glutIdleFunc(spinDisplay);
- break;
- case GLUT_MIDDLE_BUTTON:
- if(state == GLUT_DOWN)
- glutIdleFunc(NULL);
- break;
- default:
- break;
- }
- }
- /*
- * Request double buffer dispaly mode.
- * Register mouse input callback functions.
- */
- int main(int argc, char **argv) {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
- glutInitWindowSize(kWindowWidth, kWindowHeight);
- glutInitWindowPosition(100, 100);
- glutCreateWindow(argv[0]);
- initGL();
- glutDisplayFunc(DrawGLScene);
- glutReshapeFunc(ResizeGLScene);
- glutMouseFunc(mouse);
- glutMainLoop();
- return 0;
- }
阅读(882) | 评论(0) | 转发(0) |