OpenGL是一套图形编程接口(API),用于进行跨平台的图形渲染和计算。OpenGL的设计和实现是基于C语言的,它提供了一系列函数和数据结构,用于管理图形硬件和执行图形计算
OpenGL头文件与相关库
- OpenGL基本库:GL
#include<GL/gl.h>
- OpenGL Utility库:GLU
#include<GL\glu.h>
- OpenGL Utility Toolkit:GLUT
#include<GL\glut.h>
//目前一般改用FreeGlut库
OpenGL基本数据类型
OpenGL数据类型 | C语言数据类型 | 简写 |
---|---|---|
GLByte | signed char | b |
GLshort | short | s |
GLint, GLsizei | int/long | i |
GLfloat, GLclampf | float | f |
GLdouble, GLclampd | double | d |
GLubyte, GLboolean | unsigned char | ub |
GLunshort | unsigned short | us |
GLuint,GLenum, GLbitfied | unsigned int | ui |
OpenGL命名规范
- OpenGL函数名:
- 前缀小写gl,之后每个词首字母大写(Camel风格)
- glVertex(), glClearColor() …
- OpenGL函数名后缀,例如void glVertex{234}{bsifd}[v]()
- 2 or 3 or 4: 参数个数
- s or i or f or d: 数据类型简写
- v: vector, 代表一组数的指针
- glVertex3f(2.0, 4.0, 1.0);
- GLfloat pt[3] = {2.0,4.0,1.0}; glVertex3fv(pt);
- OpenGL常量和类型
- 开头GL_,全大写,下划线分割
- GL_TRIANGLES
GLUT程序结构
- 初始化绘画窗口
- 设置OpenGL渲染状态(有默认的值)
- 注册callback函数
- 重绘事件
- 窗口事件
- 键盘和鼠标等输入事件
- 进入事件处理循环
代码示例
#include"GL/glut_pch.h"
void display(void)
{
glClearColor(1.0,1.0,1.0,0.0);//设置清屏颜色为白色,透明度为 0.0
glClear(GL_COLOR_BUFFER_BIT);//清除颜色缓冲区,即将整个窗口用当前清屏颜色填充。
glColor3f(1.0,0.0,0.0);//设置当前绘图颜色为红色(R=1.0, G=0.0, B=0.0)
glutWireSphere(0.5,50,40);//绘制一个线框球体,球体半径为 0.5,经线数为 50,纬线数为 40
glutSwapBuffers();//在双缓冲模式下交换前后缓冲区,将绘制的结果显示到屏幕上
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);//初始化 GLUT 库,并传入命令行参数,用于初始化 GLUT 的状态
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);//设置显示模式为双缓冲(GLUT_DOUBLE)和 RGB 颜色模式(GLUT_RGB)
glutInitWindowSize(500,500);//设置窗口的初始大小为 500x500 像素
glutInitWindowPosition(100,100);//设置窗口在屏幕上的初始位置为 (100, 100)
glutCreateWindow("A red sphere in a white window")//创建一个窗口并设置窗口标题
glutDisplayFunc(display);//注册显示回调函数 display,当窗口需要重新绘制时将调用该函数。
glutMainLoop();//进入 GLUT 主循环,等待事件处理和用户交互,直到程序结束。
return 0;
}
窗口管理
void glutInit(int *argc, char **argv); 初始化GLUT库,该函数需要首先调用
void glutInitDisplayMode(unsigned int mode); 设置GLUT窗口显示方式,RGB还是color Index, 用单个还是双缓存
- GLUT_SINGLE 单缓存,直接在当前显示的缓存里绘画
- GLUT_DOUBLE 双缓存,在另一个缓存里绘画,画完后切换成当前缓存
void glutInitWindowPosition(int x, int y); 设置绘画窗口左上角位置
void glutInitWindowSize(int width, int height); 设置绘画窗口的宽高,以像素为单位
void glutCreateWindow(char* name); 按之前的设置建立绘画窗口,标题为给定name字符串。窗口在调用glutMainLoop()后才开始显示
显示回调函数
定义回调函数后,在glutDisplayFunc里注册这个函数,在窗口需要绘画或者重绘的时候调用
绘制3D物体
-
网格3D物体,不含面法向量
- void glutWireCube(Gldouble 𝑠𝑖𝑧𝑒);
- void glutWireSphere(Gldouble 𝑟𝑎𝑑𝑖𝑢𝑠, Glint 𝑠𝑙𝑖𝑐𝑒𝑠, Glint 𝑠𝑡𝑎𝑐𝑘𝑠);
-
实心3D物体,含面法向量,可着色
- void glutSolidCube(Gldouble 𝑠𝑖𝑧𝑒);
- void glutSolidSphere(Gldouble 𝑟𝑎𝑑𝑖𝑢𝑠, Glint 𝑠𝑙𝑖𝑐𝑒𝑠, Glint 𝑠𝑡𝑎𝑐𝑘𝑠);
Points
屏幕上的一个像素点(Pixel)
void glPointSize(GLfloat size)可以设置一个点的大小
OpenGL Vertex
- 添加一个点,使用void glVertex{234}{sidf}[v](TYPE coords);
- glVertex2s(2,4);
- glVertex4f(2.3, 1.0, -2.2, 1.0);
- GLdouble dvect[3] = {5,9,4}; glVertex3dv(dvect);
- 三维点可以有四个坐标(x, y, z, w), 这是齐次坐标。
- 默认情况下w = 1, 等价于坐标为(x, y, z)的点
- 当w<>1时,等价于三维点(x/w, y/w, z/w)
绘制点时,要在glBegin(GL_POINTS)和glEnd()之间进行:
glBegin(GL_POINTS);
glVertex2f(0.0,0.0);
glVertex2f(4.0,0.0);
glVertex2f(4.0,4.0);
glVertex2f(0.0,4.0);
glEnd();
Lines
- 给定起点和终点,画一线段
- 实线,1个像素大小
- 使用GL_LINES
glBegin(GL_LINES);
glVertex2f(0.0, 0.0);
glVertex2f(1.0, 0.0);
glVertex2f(1.0, 1.0);
glVertexwf(0.0, 1.0);
glEnd();
- 使用GL_LINES_STRIP和GL_LINE_LOOP,分别用于绘制连接的线段和闭合的线段
多边形细分
- 凸多边形:可直接画
- 非凸多边形:转化成多个凸多边形
- 一般曲面:用多边形网格近似
用给定的一组点依次画多边形:
glBegin(GL_POLYGON);
glVertex2f(0.0, 0.0);
glVertex2f(1.0, 0.0);
glVertex2f(1.0, 1.0);
glVertex2f(0.0, 1.0);
glEnd();
使用GL_TRIANGLES:每3个点画出一个三角形
使用GL_QUADS:每4个点画出一个四边形
GL_TRIANGLE_STRIP每个三角形顶点是连续连接的,每新增一个顶点会和前两个顶点形成一个三角形
GL_QUAD_STRIP每个四边形顶点是连续连接的,每新增2个顶点会和前两个顶点形成一个四边形
回调函数
OpenGL允许用户自定义与事件对应的callback函数
OpenGL事件包括:
Event | Example | OpenGL Callback Function |
---|---|---|
Keypress | KeyDown KeyUp | glutKeyboardFunc |
Mouse | leftButtonDown leftButtonUp | glutMouseFunc |
Motion | With mouse press Without | glutMotionFunc glutPassiveMotionFunc |
Window | Moving Resizing | glutReshapeFunc |
System | Idle Timer | glutIdleFunc glutTimerFunc |
Software | What to draw | glutDisplayFunc |
-
void glutMouseFunc(void (*func)(int button, int state, int x, int y));button 表示按下或释放的鼠标按钮,可能的取值包括:GLUT_LEFT_BUTTON:鼠标左键
GLUT_MIDDLE_BUTTON:鼠标中键(滚轮)
GLUT_RIGHT_BUTTON:鼠标右键
state 表示鼠标按钮的状态,可能的取值包括:
GLUT_DOWN:表示按下状态
GLUT_UP:表示释放状态
x 和 y 表示鼠标指针相对于窗口左上角的当前位置坐标。 -
void glutMotionFunc(void (*func)(int x, int y));
当鼠标键按下的同时移动鼠标位置,触发回调函数 -
void glutIdleFunc(void (*func)(void));
没有事件执行的时候,执行参数里的回调函数,func可以为null -
void glutPostRedisplay(void)
标记当前窗口需要重画,当开始glutMainLoop下个循环,OpenGL确定重绘图形窗口