开头
写在开头,推荐看一下这篇文章涨涨知识OpenGL库文件的区别(glut/glew/glfw/glad/freeglut)和环境配置
不知道从哪扒来的glut的参考文档
代码初识
其实之前学的是glfw,上学校的图形学课教的是glut(如果他发了个实验指导手册算教的话…),不过很多东西还是通用的,就目前感觉而言glut上手可能更快…此前学的glad+glfw是LearnOpenGLCN的开源教程,十分推荐。该教程的笔记稍后也会整理公布。
#define GLUT_DISABLE_ATEXIT_HACK
#include <gl/glut.h>
int gx = 50;
int gy = 100;
void onReshape(int w, int h)
{
// 设置视口大小
glViewport(0, 0, w, h);
// 切换矩阵模式为投影矩阵
glMatrixMode(GL_PROJECTION);
// 载入单位矩阵
glLoadIdentity();
// 进行二维平行投影
gluOrtho2D(0, w, h, 0);
// 切换矩阵模式为模型矩阵
glMatrixMode(GL_MODELVIEW);
// 发送重绘
glutPostRedisplay();
}
void onDisplay()
{
// 设置清屏颜色
glClearColor(1, 1, 1, 0);
// 用指定颜色清除帧缓存
glClear(GL_COLOR_BUFFER_BIT);
static char text[] = "Hello World!";
// 定位输出位置
glRasterPos2d(gx, gy);
// 设置字符串颜色
glColor3f(1, 0, 0);
for (int i = 0; text[i] != '\0'; i++)
{
// 输出字符
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, text[i]);
}
// 交换双缓存
glutSwapBuffers();
}
void onMouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
gx = x;
gy = y;
glutPostRedisplay();
}
}
int main(int argc, char* argv[])
{
// 初始化 glut
glutInit(&argc, argv);
// 设置 OpenGL 显示模式(双缓存, RGB 颜色模式)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
// 设置窗口初始尺寸
glutInitWindowSize(400, 300);
// 设置窗口初始位置
glutInitWindowPosition(100, 100);
// 设置窗口标题
glutCreateWindow("Hello");
// 设置显示回调函数
glutDisplayFunc(onDisplay);
// 设置窗口尺寸变化回调函数
glutReshapeFunc(onReshape);
// 设置鼠标事件回调函数
glutMouseFunc(onMouse);
// 进入 glut 事件循环
glutMainLoop();
return 0;
}
效果就是点哪这个文字就移动到哪。
鼠标事件
glutMouseFunc
设置当前窗口的鼠标回调。当用户在窗口中按下并释放鼠标按钮时,每次按下和释放都会生成一个鼠标回调。
鼠标事件发生后,会自动调用glut注册好的用来处理它的函数,该函数由glutMouseFunc()
注册,根据IDE提示,不难发现被注册的函数应当具有哪些参数,这正好与onMouse(int button, int state, int x, int y)
这个函数签名得到了印证。
其中buttion
取值可以是左中右键,即:GLUT_LEFT_BUTTON
、GLUT_MIDDLE_BUTTON
、GLUT_RIGHT_BUTTON
。对于只有两个鼠标按钮的系统,可能无法生成GLUT_MIDDLE_BUTTON回调。
state
是鼠标的状态,按下或松开,即:GLUT_DOWN
、GLUT_UP
x
和y
鼠标当前的窗口坐标(以左上角为原点)
在鼠标回调期间,可能会调用glutGetModifier
以确定生成回调的鼠标事件发生时修饰键(modifier keys)的状态。
将NULL
传递给glutMouseFunc()
会禁用鼠标回调的生成。
类似地还有glutEntryFunc()
设置当前窗口的鼠标输入/离开回调,其state
有两种:GLUT_LEFT
、GLUT_ENTERED
以及glutMotionFunc()
和glutPassiveMotionFunc()
。
当鼠标在窗口内移动,同时按下一个或多个鼠标按钮时调用Motion
回调,当鼠标在窗口内移动而不按下鼠标按钮时,将调用PassiveMotion
回调。
x 和 y 回调参数指示鼠标在窗口相对坐标中的位置。
类似glutMouseFunc()
,将NULL
传入会禁用相关回调的生成。
文档中有句话不太明白:If a menu is attached to a button for a window, mouse callbacks will not be generated for that button.
到时候再看看menu是啥
glutMainLoop
glutMainLoop进入GLUT事件处理循环。在GLUT程序中,此例程最多只能调用一次。一旦调用,此例程将永远不会返回。它将根据需要调用已注册的任何回调。
帧缓冲
或许可以看看《图形编程技术学习》(三十八)颜色缓冲
glutBitmapCharacter
void glutBitmapCharacter(void *font, int character);
glutBitmapCharacter
使用 OpenGL 呈现位图字符。
font
指定要使用的位图字体。
character
指定要渲染的字符(不限于 8 位)。
常见的font
有:
GLUT_BITMAP_8_BY_13
:固定宽度的字体,每个字符都适合 8 x 13 像素的矩形。GLUT_BITMAP_9_BY_15
GLUT_BITMAP_TIMES_ROMAN_10
:10 磅比例间隔的times roman字体。GLUT_BITMAP_TIMES_ROMAN_24
GLUT_BITMAP_HELVETICA_10
:10 点比例间隔的赫尔维卡字体。GLUT_BITMAP_HELVETICA_12
GLUT_BITMAP_HELVETICA_18
渲染不存在的字符不起作用。glutBitmapCharacter
会自动设置OpenGL解压缩像素存储模式,并在返回之前保存和恢复以前的模式。生成的对 glBitmap 的调用将根据字符的宽度调整当前栅格位置。
glutPostRedisplay
glutPostRedisplay
将当前窗口标记为需要重新显示,通过glutMainLoop()
的下一次迭代,
即使有多个glutPostRedisplay()
,在下一次回调时也会只生成一个redisplay
回调。
关于onReshape
void onReshape(int w, int h)
{
// 设置视口大小
glViewport(0, 0, w, h);
// 切换矩阵模式为投影矩阵
glMatrixMode(GL_PROJECTION);
// 载入单位矩阵
glLoadIdentity();
// 进行二维平行投影
gluOrtho2D(0, w, h, 0);
// 切换矩阵模式为模型矩阵
glMatrixMode(GL_MODELVIEW);
// 发送重绘
glutPostRedisplay();
}
gluOrtho2D
定义了一个二维图像投影矩阵。
若不调用gluOrtho2D()
,窗口会显示-1<x<1,-1<y<1这个区域。如果调用gluOrtho2D(x1,x2,y,1y2),则窗口会显示x1<x<x2,y1<y<y2这个区域。
在没调用gluOthor2D
函数之前,坐标范围是 X:-1~1,Y:-1~1;调用了这个函数之后坐标范围是 X:0~w,Y:0~h
参考
这篇文章看着不错