OpenGL - OpenGL 编程简介
OpenGL 是开发的图形编程库,是调用图形硬件程序的接口,由大约150个函数组成,用户可以来完成各种绘图任务
1.1 OpenGL可以做什么
- 变换,几何编程,投影变换,视口变换
- 光照与材质
- 纹理映射
- 图像功能,anti-aliasing(反混淆),for,blending(混合)…
- 特效,深度检测,运动模糊…
- 建模…
注意:OpenGL 不是用来建模的,是用来渲染的,它的大部分函数是用来设置流水线渲染的
OpenGL的学习绝不能只是学习一堆离散的函数,而必须很好的理解图形流水线的整体流程及各个环节,否则学习OpenGL函数,如同盲人摸象
OpenGL是一个状态机
- 整个绘制操作会按照固定的流程进行,如同一条流水线
- OpenGL函数只是用来设置这条流水线的一系列状态参数,而并不是用来真正执行绘制操作的
在引入了Shader编程之后,OpenGL出现了两种编程模式
- 固定流水线模式 — 传统方式
- Shader编程模式 — 现代方式
1.2 OpenGL的学习路线
-
传统方式
学习固定流水线,然后过度到shader编程,《OpenGL编程指南》第7版(红宝书)及其以前采用的是传统方式,从第8版开始转入现代方式
-
现代方式
直接学习shader编程模式,《OpenGL超级宝典》(蓝宝书)
-
网站学习
下面两个站点都是现代的shader方式
https://learnopengl.com/ (glfw + glad)
http://ogldev.atspace.co.uk/ (freeflut + glew)
本课程学习方式
选择传统方式学习
- 现代依然有大量的程序是固定流水线模式;
- 传统方式可以让我们更容易理解图形流水线;
1.3 OpenGL相关的库
1. 核心库
- 包括115个函数,前缀
gl
- 例如:glColor3f(),glTranslate3f()
- gl.h,openGL32.lib,openGL32.dll
2. 实用程序库
- 包括43个函数,前缀
glu
- gluPerspective()
- glu.h,glu.lib,glu.dll
特点:都具有跨平台性(接口方法名是一样的),OpenGL的核心库和实用库接口可以在任何OpenGL的实现平台上实用
3. 辅助工具库
- 如 freeglut ,开源的OpenGL工具库
提供功能大致如下:
- 执行与窗口相关的功能
- 鼠标,键盘交互功能
- 右键菜单功能
- 高级的建模命令
1.3 OpenGL基本语法
其函数定义有很强的规范性,如下面这个函数的定义
1. 命名规范
void glVertex3fv(Glfloat *vvertex);
- 前缀 gl,glu,glut—表明是函数是输入那个函数库
- 后缀
- 2、3、4表示参数的维数
- b、s、i、f、d、ub、us、ui,表示参数的数据类型
- v—表示以数组方式传递参数
2. 数据类型
后缀 | 数据类型 | 在C中的类型 | OpenGL中的定义 |
---|---|---|---|
b | 8-bit integer | signed char | GLbyte |
s | 16-bit integer | short | GLshort |
i | 32-bit integer | int ot long | GLint,GLsizei |
f | 32-bit floating point | float | GLfloat,GLclampf |
d | 64-bit floating point | double | GLdouble,GLclampd |
ub | 8-bit unsigned integer | unsigned char | GLubytc,GLboolean |
us | 16-bit unsigned integer | unsigned short | GLushort |
ui | 32-bit unsigned integer | unsigned int or unsigned long | GLuint,GLenum,GLbitfield |
3. 基本语法
每个顶点有x、y、z三个坐标值,有时候还会有第四个坐标值 w,如下这个函数的调用
glVertex3f(2.0f, 4.0f, 5.0f);//这种方式直接传递数据
GLfloat v[3] = {3.0f,4.0f,5.0f};
glVertex3fv(v);//传参直接传递一个数组进来
每个颜色值有4个分量,rgba
glColor4f(1.0f,1.0f,1.0f,0.5f);
glColorub(255,0,0);// 无符号值0-255
一些常量符号
GL_RGB...
绘制基本图元的方法
glBegin(GL_TRIANGLES);
glVertex3f(x1,y1,z1);
glVertex3f(x2,y2,z2);
glVertex3f(x3,y3,z3);
glEnd();
// 上面还可以设置顶点的颜色和法向
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f);
glVertex3f(x1,y1,z1);
glVertex3f(x2,y2,z2);
glVertex3f(x3,y3,z3);
glEnd();
4. 问题集合
1. Freeglut 编程的基本模式
main()
{
设置显示模式;
初始化窗口;
创建窗口;
设置一系列回调函数;
启动主循环;
}
其基本模式是一个大循环,系统由消息来驱动,进行绘图
2. glutIdleFunc(display)
这个函数的作用是,在任何时候都会定时调用其中传递过来的函数display
,因此会占用很大的资源,但是可以考虑不使用这个函数,在需要调用display的地方告诉循环此时需要调用
可以使用glutPostRedisplay()
,通知glut开始调用display(),例如档窗口大小发生变化的时候,就明确告诉程序调用display()
进行重新绘制,例如下面在触发键盘事件的时候进行重绘
void processNormalKeys(unsigned char key, int x, int y)
{
printf("the key string is %c\n", key);
switch (key) {
case 'a':
G_fDistance -= 0.1f;
break;
case 'd':
G_fDistance += 0.1f;
break;
case 27: //"esc"
exit(0);
}
glutPostRedisplay();// 监听到消息时进行重绘
}
3. 默认坐标系和视点
OpenGL的默认坐标系,是右手坐标系
默认的视点在原点位置(0,0,0),是处于屏幕中心的,视线方向是沿Z
轴负方向
OpenGL是一个状态机,整个绘制操作会按照固定的流程进行,如同一条流水线,OpenGL函数只是用来设置这条流水线的一些状态参数,而并不是用来真正执行绘制操作的