65.9K
CodeProject 正在变化。 阅读更多。
Home

GLUT 窗口模板

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (26投票s)

2007年7月26日

CPOL

16分钟阅读

viewsIcon

204831

downloadIcon

6897

本文详细介绍了如何设置第一个 OpenGL FreeGLUT 窗口,并为您提供 OpenGL 应用程序的模板

Visual C++ 2015 文件

Visual C++ 6 文件(旧)

Screenshot - GLUT_Window_Template.jpg

目录

引言

本程序使用 GLUT 库设置了一个平台无关的 OpenGL 窗口。它可以用于以下方面:

  • 通过交互式程序学习 GLUT 和 OpenGL
    • 交互式程序
    • 文档
    • 源代码
  • 启动你的第一个 OpenGL 程序
  • 将代码用作 OpenGL 应用程序的模板

在下载和运行程序之前,请务必阅读文档的“运行程序”部分。

什么是 OpenGL?

OpenGL 是用于开发可移植二维和三维图形应用程序的最广泛使用的 API 之一。它最初由 Silicon Graphics 于 1992 年开发,目前由 OpenGL ARB(架构审查委员会)控制和维护。ARB 的代表包括 SGI、Microsoft、Apple、nVidia、ATI、Intel、id Software(以创建 DOOM 和 QUAKE 而闻名)以及 3D Labs。

OpenGL 因其易用性、可移植性、稳定性和丰富的文档而成为行业标准和非常受欢迎的 API。根据 OpenGL.org 的说法,OpenGL 是唯一真正开放、厂商中立、跨平台图形标准。

本文最初基于 OpenGL 2.1 撰写,但应与最新的 OpenGL 4.5 版本兼容。我没有找到 4.5 的 dll,因此这里使用的 dll 仍然是 2.1 的。

为什么使用 GLUT?

OpenGL 是一个与窗口系统无关的图形库。这意味着它不处理特定于操作系统的窗口系统操作。这样做的目的是使 OpenGL 能够移植到新的平台。创建渲染窗口和处理事件的任务留给本机窗口系统定义。OpenGL 实用工具包 (GLUT) 旨在弥补这一差距,从而为 OpenGL 程序开发者提供了一个与窗口系统无关的 API。GLUT 支持以下功能:

  • 窗口管理
  • 事件处理
  • 右键菜单
  • 渲染字体
  • 渲染各种实心和线框对象
  • 从复杂的输入设备读取

需要注意的是,GLUT 不是一个功能齐全的窗口工具包。它主要用于学习 OpenGL 和开发简单的 OpenGL 程序。GLUT 简单、易用且小巧。GLUT 库提供 C、C++、FORTRAN 和 Ada 编程绑定。它可以移植到几乎所有 X Window 系统和 Windows 的 OpenGL 实现。 

重要提示: GLUT 自 1998 年以来就未更新过。一个更好的替代方案是 FreeGLUT。本文最初基于 GLUT 3.6 版本撰写,现已过渡为与 FreeGLUT 兼容。

为什么需要 GLUT 窗口模板?

考虑到 OpenGL 是一个面向图形应用程序的 API,很明显,渲染图形对象总是需要一个窗口。为了避免每次创建使用 OpenGL 的图形应用程序时都要编写相同的代码,可以使用此程序代码作为模板,让您直接开始关注程序中真正重要的事情。OpenGL GLUT 窗口模板具有以下属性:

  • 标题:“GLUT 窗口模板”
  • 背景颜色:黑色 (R = 0, G = 0, B = 0)
  • 尺寸:宽度 = 480,高度 = 480
  • 位置:x = (屏幕宽度 - 窗口宽度) / 2,y = (屏幕高度 - 窗口高度) / 2。这意味着窗口将居中显示在屏幕上。
  • 处理键盘、鼠标和显示事件
  • 通过命令提示符显示事件发生及其含义

在 Windows 上使用

我强烈建议您查阅官方 OpenGL Wiki 上的说明,了解如何在 Windows、Linux 和 Mac 上开始使用 OpenGL: https://www.opengl.org/wiki/Getting_Started

Visual C++ 2015 (14.0)

如今,使用最新版本的 Visual Studio 启动 OpenGL GLUT 应用程序真是太方便了。您只需要安装 NupenGL.Core nuget 包即可。无需再处理 .h、.lib 和 .dll 文件。因此,请忽略下面的“Visual C++ 6”部分,因为它写于 9 年前,适用于 Visual C++ 6 版本(我们现在是 14 版本!)。

以下是从头开始的简单步骤:

  • 打开 Visual Studio 2015 Community Edition
  • 创建一个新的 Visual Studio C++ Windows 控制台应用程序


     
  • 保持为空即可


     
  • 安装 NupenGL.Core nuget 包。在 Visual Studio 中,转到“工具”>“NuGet 包管理器”>“管理此解决方案的 NuGet 程序包”。搜索“NupenGL”并安装该包。


     
  • 将 *GLUT_Window_Template.c* 添加到您的项目中
  • 当前的 NunpenGL.Core nuget 包 (0.0.0.1) 是为与 Visual Studio 2013 配合使用而设计的。需要更新才能在 Visual Studio 2015 中正常运行。如果构建,您会收到此错误:“LNK1104    无法打开文件 'freeglut.lib'”。要解决此问题,请转到“项目属性”,并将“平台工具集”设置为“Visual Studio 2013 (v120)”,这样您就可以在没有问题的情况下进行构建和运行。

Visual C++ 6 (忽略)

运行程序

为了运行程序,需要三个动态链接库 (DLL):*opengl32.dll*、*glu32.dll* 和 *glut32.dll*。*opengl32.dll* 和 *glu32.dll* 文件已随您的 Windows 操作系统一同提供,位于系统文件夹中。要运行可执行文件,您需要下载 *glut32.dll* 并将其复制到与您的 exe 相同的文件夹中,或者放在系统路径中的一个文件夹中。您可以在附加的 ZIP 文件 *GLUT_Window_Template_dll.zip* 的 *Visual C++\dll* 子文件夹中找到所有 DLL 文件。

使用 Microsoft Visual C++ 编译代码

为了在 Windows 平台上使用 Microsoft Visual Studio 编写 C OpenGL 应用程序,您需要以下文件:

  • C 头文件:*GL.h*、*GLU.h* 和 *GLUT.h*
  • C LIB 文件:*glui32.lib*、*opengl32.lib* 和 *glut32.lib*

您可以在附加的 ZIP 文件 *GLUT_Window_Template_dll.zip* 的 *Visual C++\include\GL* 和 *Visual C++\lib* 子文件夹中找到所有头文件和 LIB 文件。

Microsoft Visual C++ 6

要在 Visual C++ 6.0 环境中使用代码,请执行以下步骤:

  • 打开 Microsoft Visual C++ 6.0
  • 创建一个新的 Win32 控制台应用程序项目

    Screenshot - GLUT_Window_Template_1.jpg
  • 将源文件 *GLUT_Window_Template.c* 复制到您的项目文件夹。在我们的例子中,这是 GLUT_Window_Template_src。您可能需要重命名该文件以满足您的程序需求。
  • 使用菜单选项 Project\Add To Project\Files 将源文件添加到项目中

    Screenshot - GLUT_Window_Template_2.jpg
  • 确保头文件在 include 文件夹中,LIB 文件在 lib 文件夹中,DLL 文件在系统文件夹中。
     
    文件 描述 源文件夹(已附加) 目标文件夹
    GL.H、GLU.H、GLUT.H 头文件 Visual C++\include\GL C:\Program Files\Microsoft Visual Studio\VC98\Include\GL
    OPENGL32.LIB、GLU32.LIB、GLUT32.LIB Lib 文件 Visual C++\lib C:\Program Files\Microsoft Visual Studio\VC98\Lib
    OPENGL32.DLL、GLU32.DLL、GLUT32.DLL DLL 文件 Visual C++\dll C:\WINDOWS\system32
  • 将代码链接到库

    Screenshot - GLUT_Window_Template_3.jpg

    为了避免在您创建的每个 Visual C++ 6.0 项目中都设置链接设置,您可以在代码中包含以下代码段,它基本上与上面的操作相同。
     
    // Link the lib files to the program. This is not necessary
    // if you have added the lib names using Project/Settings/Link
    #pragma comment (lib, "opengl32.lib")
    #pragma comment (lib, "glut32.lib")
    #pragma comment (lib, "glu32.lib")
  • 为了避免在您想要运行 OpenGL 窗口时出现控制台窗口,您可以在代码中包含此指令:
     
    #pragma comment(
        linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

Using the Code

源代码旨在用作您 OpenGL 应用程序的模板。要在新应用程序中使用它,您可以简单地重命名 C 文件并将其添加到您的 Visual Studio 项目中。

代码解释

应使用以下 include 指令在 GLUT 程序中包含 GLUT 的头文件:

  #include <GL/glut.h>  

无需包含 `<GL/gl.h>` 或 `<GL/glu.h>`,因为 `<GL/glut.h>` 已经包含了它们。您也可以使用 `<GL/freeglut.h>`。

初始化

以 `glutInit` 开头的函数用于初始化 GLUT 状态。`glutInit` 函数是主要的初始化例程,在一个 GLUT 程序中只能调用一次。不允许在主 `glutInit` 函数调用之前调用不以 `glutInit` 开头的 OpenGL 或 GLUT 函数。但是,可以在主 `glutInit` 函数调用之前调用其他以 `glutInit` 开头的函数。这样做的目的是允许在命令行参数中指定窗口初始化状态,并在与窗口系统协商会话之前。

下面我将展示每个初始化函数的原型、其描述以及我在程序中的用法。

连接到窗口系统

void glutInit(int *argcp, char **argv);

`glutInit` 初始化 GLUT 库并与窗口系统协商会话。

glutInit(&argc, argv);

设置窗口大小

void glutInitWindowSize(int width, int height);  

使用 `glutInitWindowSize` 设置将要创建的窗口的初始大小。`width` 和 `height` 参数的值必须大于零。如果未指定值(即未调用该函数),则默认窗口大小为 300 x 300。请注意,窗口系统不一定会遵循此信息。因此,GLUT 程序必须依赖 `glutReshapeFunc` 来确定窗口的实际大小。

//  variables representing the window size
int window_width = 240;
int window_height = 240;

//  Set the window size
glutInitWindowSize (window_width, window_height); 

设置窗口位置

void glutInitWindowPosition(int x, int y);  

使用 `glutInitWindowPosition` 设置窗口的初始位置。默认值为 -1 by -1,这意味着窗口系统将确定合适的位置。

//  define the window position on screen
int window_x;
int window_y;

//-------------------------------------------------------------------------
//  This function sets the window x and y coordinates
//  such that the window becomes centered
//-------------------------------------------------------------------------
void centerOnScreen (void)
{
    window_x = (glutGet (GLUT_SCREEN_WIDTH) - window_width)/2;
    window_y = (glutGet (GLUT_SCREEN_HEIGHT) - window_height)/2;
}

//  Set the window position
glutInitWindowPosition (window_x, window_y);

在上面的代码中,我只是简单地将窗口居中显示在屏幕上。`glutGet (GLUT_SCREEN_WIDTH)` 获取屏幕宽度(以像素为单位),`glutGet (GLUT_SCREEN_HEIGHT)` 获取屏幕高度。

设置显示模式

void glutInitDisplayMode(unsigned int mode);  

显示模式指定了用于渲染 OpenGL 图形的缓冲区。可以使用逻辑 `OR` 运算符选择多个模式。以下是可选项,已从 GLUT API Version 3 Reference Manual 复制:

模式 描述
GLUT_INDEX 位掩码,用于选择颜色索引模式窗口。如果也指定了 `GLUT_RGBA`,则此选项会覆盖它。
GLUT_SINGLE 位掩码,用于选择单缓冲窗口。如果未指定 `GLUT_DOUBLE` 或 `GLUT_SINGLE`,则默认为此项。
GLUT_DOUBLE 位掩码,用于选择双缓冲窗口。如果也指定了 `GLUT_SINGLE`,则此选项会覆盖它。
GLUT_ACCUM 位掩码,用于选择带有累加缓冲区的窗口。
GLUT_ALPHA 位掩码,用于选择带有 Alpha 分量(用于颜色缓冲区)的窗口。
GLUT_DEPTH 位掩码,用于选择带有深度缓冲区的窗口。
GLUT_STENCIL 位掩码,用于选择带有模板缓冲区的窗口。
GLUT_MULTISAMPLE 位掩码,用于选择支持多重采样的窗口。如果多重采样不可用,则会自动选择一个不支持多重采样的窗口。注意:OpenGL 客户端和服务器端实现都必须支持 `GLX_SAMPLE_SGIS` 扩展才能使用多重采样。
GLUT_STEREO 位掩码,用于选择立体窗口。
GLUT_LUMINANCE 位掩码,用于选择具有“亮度”颜色模型的窗口。此模型提供了 OpenGL RGBA 颜色模型的功能,但帧缓冲区中不保留绿色和蓝色分量。相反,每个像素的红色分量会被转换为零到 `glutGet(GLUT_WINDOW_COLORMAP_SIZE)-1` 之间的索引,并在每个窗口的颜色映射表中查找,以确定窗口内像素的颜色。`GLUT_LUMINANCE` 窗口的初始颜色映射被初始化为线性灰度渐变,但可以使用 GLUT 的颜色映射例程进行修改。

 

 

glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);

 

 

要在窗口上显示图形内容,我们需要告诉 GLUT 使用单缓冲还是双缓冲。如果使用单缓冲,我们需要将 `mode` 设置为 `GLUT_SINGLE`(默认)。要显示 OpenGL 内容在窗口上,我们必须调用 `glFlush` OpenGL 函数,该函数将帧缓冲区的 Gopy 复制到窗口上可见的 Gopy。

然而,`GLUT_DOUBLE` 通常是更好的选择,因为它允许更快的图形渲染,并且由于使用了两个连续交换的帧缓冲区而不会出现闪烁。要交换这些缓冲区,我们调用 GLUT 函数 `glutSwapBuffers`。请注意,由于使用了 2 个帧缓冲区而不是 1 个,`GLUT_DOUBLE` 比 `GLUT_SINGLE` 占用更多内存。

创建窗口

int glutCreateWindow(char *name);  

使用 `name` 作为标题创建 GLUT 窗口。返回的值是窗口的唯一小型整数标识符。在调用 `glutMainLoop` 函数之前,渲染到已创建的窗口无效,因为窗口尚无法显示。

//  variable representing the window title
char *window_title = "GLUT Window Template";

//  Create Window
glutCreateWindow (window_title);

创建窗口后,您可能希望将其全屏显示。

//  Tells whether to display the window full screen or not
//  Press Alt + Esc to exit a full screen.
int full_screen = 0;

//  View in full screen if the fullscreen flag is on
if (full_screen)
    glutFullScreen ();

设置程序初始状态

这里的目的是设置一些 OpenGL 属性并初始化程序中的任何数据结构。在我们的例子中,我们需要将帧缓冲区清除颜色设置为黑色。这意味着每当我们想要刷新图形时,我们都需要先用黑色画布清除旧的绘图,然后再重绘新的内容。否则,我们的图形将无法正确显示。

//-------------------------------------------------------------------------
//  Set OpenGL program initial state.
//-------------------------------------------------------------------------
void init ()
{
    //  Set the frame buffer clear color to be black.
    glClearColor (0.0, 0.0, 0.0, 0.0);
} 

`glClearColor` 的参数是 `R`(红色)、`G`(绿色)、`B`(蓝色)和 `A`(Alpha)。Alpha 用于透明度。值范围在 0.0 到 1.0 之间。例如,如果您想将清除颜色设置为灰色(128, 128, 128),则需要将每个分量除以 255 才能获得 `glClearColor` 的正确参数。

设置回调函数

// Set the callback functions
glutDisplayFunc (display);
glutReshapeFunc  (reshape);
glutMouseFunc (mouse);
glutMotionFunc (motion);
glutPassiveMotionFunc (pmotion);
glutKeyboardFunc (keyboard);
glutSpecialFunc (special);

这些是最常用的回调函数。要查看 GLUT 支持的其余回调函数,请参考 GLUT API Version 3 Reference Manual

glutDisplayFunc

//-------------------------------------------------------------------------
//  This function is passed to glutDisplayFunc in order to display
//    OpenGL contents on the window.
//-------------------------------------------------------------------------
void display (void)
{
    //  Clear the window or more specifically the frame buffer...
    //  This happens by replacing all the contents of the frame
    //  buffer by the clear color (black in our case)
    glClear (GL_COLOR_BUFFER_BIT);

    //  Draw scene
    drawObject ();

    //  Swap contents of backward and forward frame buffers
    glutSwapBuffers ();
}

`glClear (GL_COLOR_BUFFER_BIT)` 将清除帧缓冲区,以便可以清晰地重新绘制内容。`glutSwapBuffer` 将后缓冲区的 Gopy 放入窗口上可见的前缓冲区的 Gopy 中。

`drawObject` 函数简单地显示一个二十面体,并告诉我们 `display` 函数当前正在被调用。当 GLUT 确定窗口需要重绘时,将调用窗口的 `display` 回调。GLUT 中的 `display` 回调函数可以通过调用 `glutPostRedisplay` 来显式设置,也可以作为窗口系统报告的窗口损坏的结果隐式设置。GLUT 会将窗口的多个已发布重绘合并,以最大程度地减少调用 `display` 回调的次数。

//-------------------------------------------------------------------------
//  Draws our object.
//-------------------------------------------------------------------------
void drawObject ()
{
    //  Show when are displaying an object
    printf ("Displaying object...\n");

    //  Draw Icosahedron
    glutWireIcosahedron ();
}

您将在以下情况下在命令提示符中看到“正在显示对象…”消息:

  • `glutPostRedisplay` 在代码中显式调用
  • 窗口调整大小后
  • 窗口失去焦点然后重新获得焦点时

如果您在其他情况下看到这种情况,请告知我。

glutReshapeFunc

//-------------------------------------------------------------------------
//  This function is passed to the glutReshapeFunc and is called
//  whenever the window is resized.
//-------------------------------------------------------------------------
void reshape (int w, int h)
{
    //  Stay updated with the window width and height
    window_width = w;
    window_height = h;

    //  Reset viewport
    glViewport(0, 0, window_width, window_height);

    //  Print current width and height on the screen
    printf ("Window Width: %d, Window Height: %d.\n",
        window_width, window_height);
}

`reshape` 函数将在每次窗口调整大小时以及窗口首次显示在屏幕上时被调用。回调的 `w` 和 `h` 参数以像素为单位指定了新的窗口大小。

我在这里使用 `glViewport` 函数来在窗口大小调整时将绘图区域重置为等于窗口大小。如果您尝试注释掉 `glViewport` 函数,您会注意到绘图内容会保持不变,无论您如何调整窗口大小。但是,调用 `glViewport` 函数将根据窗口大小的变化放大和缩小绘图区域。

glutMouseFunc

当用户按下和释放鼠标按钮时,会生成两个事件:一个用于按下,另一个用于释放。`state` 参数为 `GLUT_UP` 或 `GLUT_DOWN`,分别表示回调是由于释放还是按下引起的。`button` 参数为 `GLUT_LEFT_BUTTON`、`GLUT_MIDDLE_BUTTON` 或 `GLUT_RIGHT_BUTTON` 之一,表示哪个按钮被点击。`x` 和 `y` 参数表示鼠标坐标相对于 GLUT 窗口时鼠标按钮状态的变化。如果菜单附加到窗口的某个按钮,则不会为该按钮生成鼠标回调。将 `NULL` 传递给 `glutMouseFunc` 会禁用鼠标回调的生成。

//-------------------------------------------------------------------------
//  This function is passed to the glutMouseFunc and is called
//  whenever the mouse is clicked.
//-------------------------------------------------------------------------
void mouse (int button, int state, int x, int y)
{
    switch (button)
    {
        //  Left Button Clicked
        case GLUT_LEFT_BUTTON:

            switch (state)
            {
                //  Pressed
                case GLUT_DOWN:
                    printf ("Mouse Left Button Pressed (Down)...\n");
                    break;
                //  Released
                case GLUT_UP:
                    printf ("Mouse Left Button Released (Up)...\n");
                    break;
            }

            break;

        //  Middle Button clicked
        case GLUT_MIDDLE_BUTTON:

            switch (state)
            {
                //  Pressed
                case GLUT_DOWN:
                    printf ("Mouse Middle Button Pressed (Down)...\n");
                    break;
                //  Released
                case GLUT_UP:
                    printf ("Mouse Middle Button Released (Up)...\n");
                    break;
            }

            break;

        //  Right Button Clicked
        case GLUT_RIGHT_BUTTON:

            switch (state)
            {
                //  Pressed
                case GLUT_DOWN:
                    printf ("Mouse Right Button Pressed (Down)...\n");
                    break;
                //  Released
                case GLUT_UP:
                    printf ("Mouse Right Button Released (Up)...\n");
                    break;
            }

            break;
    }
}

为了在鼠标事件发生时检查 Shift、Ctrl 或 Alt 键是否被按下,我们可以使用 `glutGetModifiers` 函数。它返回输入事件(键盘、特殊键或鼠标回调)生成时修改键的状态。修饰键是 `GLUT_ACTIVE_SHIFT`(Shift 或 Caps Lock)、`GLUT_ACTIVE_CTRL`(Ctrl)和 `GLUT_ACTIVE_ALT`(Alt)。

glutMotionFunc

只要用户在按下按钮的同时移动鼠标(即拖动),此事件就会连续调用。

//-------------------------------------------------------------------------
//  This function is passed to the glutMotionFunc and is called
//  whenever the mouse is dragged.
//-------------------------------------------------------------------------
void motion (int x, int y)
{
    //  Print the mouse drag position
    printf ("Mouse Drag Position: %d, %d.\n", x, y);
}

glutPassiveMotionFunc

只要用户在未按下按钮的情况下移动鼠标,此事件就会连续调用。

//-------------------------------------------------------------------------
//  This function is passed to the glutPassiveMotionFunc and is called
//  whenever the mouse is moved.
//-------------------------------------------------------------------------
void pmotion (int x, int y)
{
    //  Print mouse move position
    printf ("Mouse Move Position: %d, %d.\n", x, y);
}

glutKeyboardFunc

每个生成 ASCII 字符的按键都会生成一个键盘回调。`key` 回调参数是生成的 ASCII 字符。`x` 和 `y` 回调参数表示按键时窗口相对坐标中的鼠标位置。将 `NULL` 传递给 `glutKeyboardFunc` 会禁用键盘回调的生成。

//-------------------------------------------------------------------------
//  This function is passed to the glutKeyboardFunc and is called
//  whenever the user hits a key.
//-------------------------------------------------------------------------
void keyboard (unsigned char key, int x, int y)
{
    //  Print what key the user is hitting
    printf ("User is hitting the '%c' key.\n", key);
    printf ("ASCII code is %d.\n", key);

    switch (key)
    {
        //  User hits A key
        case 'a':

            break;

        //  User hits Shift + A key
        case 'A':

            break;

        //  User hits Enter
        case 13:
            printf ("User is hitting the Return key.\n");
            break;

        //  User hits Space
        case 32:
            printf ("User is hitting the Space key.\n");
            break;

        //  User hits back space
        case 8:
            printf ("User is hitting the Back Space key.\n");
            break;

        //  User hits ESC key
        case 27:
            exit (1);
            break;
    }

    glutPostRedisplay ();
}

为了在按下 ASCII 键时检查 Shift、Ctrl 或 Alt 键是否被按下,我们可以使用 `glutGetModifiers` 函数。此外,修饰键也可能影响 ASCII 字符本身。例如,如果 Caps Lock 关闭,我们按下 Shift + A 键,`key` 参数的值将设置为 `A`。如果只按下 A 键,则 `key` 参数设置为 `a`。

glutSpecialFunc

//-------------------------------------------------------------------------
//  This function is passed to the glutSpecialFunc and is called
//  whenever the user hits a special key.
//-------------------------------------------------------------------------
void special (int key, int x, int y)
{
    switch (key)
    {
        case GLUT_KEY_F1 :
            printf ("F1 function key.\n");
            break;
        case GLUT_KEY_F2 :
            printf ("F2 function key. \n");
            break;
        case GLUT_KEY_F3 :
            printf ("F3 function key. \n");
            break;
        case GLUT_KEY_F4 :
            printf ("F4 function key. \n");
            break;
        case GLUT_KEY_F5 :
            printf ("F5 function key. \n");
            break;
        case GLUT_KEY_F6 :
            printf ("F6 function key. \n");
            break;
        case GLUT_KEY_F7 :
            printf ("F7 function key. \n");
            break;
        case GLUT_KEY_F8 :
            printf ("F8 function key. \n");
            break;
        case GLUT_KEY_F9 :
            printf ("F9 function key. \n");
            break;
        case GLUT_KEY_F10 :
            printf ("F10 function key. \n");
            break;
        case GLUT_KEY_F11 :
            printf ("F11 function key. \n");
            break;
        case GLUT_KEY_F12 :
            printf ("F12 function key. \n");
            break;
        case GLUT_KEY_LEFT :
            printf ("Left directional key. \n");
            break;
        case GLUT_KEY_UP :
            printf ("Up directional key. \n");
            break;
        case GLUT_KEY_RIGHT :
            printf ("Right directional key. \n");
            break;
        case GLUT_KEY_DOWN :
            printf ("Down directional key. \n");
            break;
        case GLUT_KEY_PAGE_UP :
            printf ("Page up directional key. \n");
            break;
        case GLUT_KEY_PAGE_DOWN :
            printf ("Page down directional key. \n");
            break;
        case GLUT_KEY_HOME :
            printf ("Home directional key. \n");
            break;
        case GLUT_KEY_END :
            printf ("End directional key. \n");
            break;
        case GLUT_KEY_INSERT :
            printf ("Inset directional key. \n");
            break;
    }

    glutPostRedisplay ();
}

每个生成非 ASCII 字符的按键都会生成一个特殊回调。`x` 和 `y` 回调参数表示按键时窗口相对坐标中的鼠标位置。将 `NULL` 传递给 `glutSpecialFunc` 会禁用特殊回调的生成。以下是 GLUT API Version 3 Reference Manual 中指定的特殊键列表:

描述
GLUT_KEY_F1 F1 功能键。
GLUT_KEY_F2 F2 功能键。
GLUT_KEY_F3 F3 功能键。
GLUT_KEY_F4 F4 功能键。
GLUT_KEY_F5 F5 功能键。
GLUT_KEY_F6 F6 功能键。
GLUT_KEY_F7 F7 功能键。
GLUT_KEY_F8 F8 功能键。
GLUT_KEY_F9 F9 功能键。
GLUT_KEY_F10 F10 功能键。
GLUT_KEY_F11 F11 功能键。
GLUT_KEY_F12 F12 功能键。
GLUT_KEY_LEFT 左方向键。
GLUT_KEY_UP 上方向键。
GLUT_KEY_RIGHT 右方向键。
GLUT_KEY_DOWN 下方向键。
GLUT_KEY_PAGE_UP Page Up 方向键。
GLUT_KEY_PAGE_DOWN Page Down 方向键。
GLUT_KEY_HOME Home 方向键。
GLUT_KEY_END End 方向键。
GLUT_KEY_INSERT Insert 方向键。

开始事件处理

void glutMainLoop(void);

在 GLUT 程序完成初始设置(例如创建窗口和菜单)后,GLUT 程序通过调用 `glutMainLoop` 进入 GLUT 事件处理循环。此函数在一个 OpenGL 程序中最多只能调用一次。

结论

我认为这篇文章可以极大地帮助您开始使用 OpenGL。同时,该模板可用于节省大量从旧项目或互联网复制粘贴的时间。如果您觉得此模板有用或有任何建议,请告诉我。

参考文献

修订历史

8/10/2015

  • 提高对 GLUT 应被 FreeGlut 取代的认识
  • 展示如何轻松地在 Visual Studio 2015 Community Edition 和 Nupengl Nuget 包中进行设置

26/07/2007

  • 应作者要求转载文章

2007 年 7 月中旬

  • 应作者要求删除文章

02/07/2007

  • 添加了参考文献部分

06/06/2007

21/05/2005:

  • 原始文章发布
© . All rights reserved.