三、OpenGL 简单开始 --- 简单三角形绘制(vertex buffer & shader pre)
上一篇:二、OpenGL 简单开始 --- 从“规范”到“调用”
下一篇:四、OpenGL 简单开始 --- 着色器(shader)
1. 缓冲区 和 着色器
简单介绍:
- C++ 程序在 CPU 运行,缓冲区存放 CPU 给 GPU 的数据;
- 着色器是在 GPU 运行的程序,通过 drawcall 取缓冲区数据利用 GPU 进行渲染。
2. OpenGL 工作模式是个 “状态机”
工作模式:你告诉他,用什么缓冲区(定义的),用哪个着色器(GPU 内的),绘制什么样的三角形(图形数据),然后他帮你完成。
- 缓冲区:定义大小、编号;
- 着色器:如何读取数据(告诉 OpenGL 数据布局),使用数据;
- 数据:图形数据,存入缓存。
2.1 状态机概念

- 状态机(State Machine)是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。
- 状态(State),现实事物是有不同状态的,例如自动门,有 open 和 closed 两种状态。有限状态机,即被描述的事物状态数量是有限个,例如自动门状态是两个 open 和 closed。
- 事件 (Event),执行某个操作的触发条件或者口令。对于自动门,“人接近和远离”就是事件。
- 动作 (Action),事件发生以后要执行动作。例如事件“人接近”,动作是“开门”;编程的时候,一个 Action 一般就对应一个函数。
- 变换 (Transition),也就是从一个状态变化为另一个状态。例如“开门过程”就是一个变换。
这样看,我们利用 GLEW 使用 OpenGL 的时候,编写的都是事件 Event 指令,OpenGL 负责通过指令,进行工作状态的转换,调用 GPU 上实现的函数 Action。
3. 代码参考
3.1 数据 和 缓冲区
GL 的 API 参考地址。
主要学习 glGenBuffers,glBindBuffer,glBufferData
缓冲区数据的使用方式的参考如下:

......
/* --- Draw A Triangle --- */
// !数据 !
float posintions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
// !数据 !
// ! 缓冲区 !
unsigned int buffer;
// 生成缓冲区
glGenBuffers(1, &buffer); // 缓冲区个数 和 缓冲区编号
// 绑定缓冲区 给 缓冲区数组
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// 存入数据
glBufferData
(
GL_ARRAY_BUFFER, // 缓冲区对象
6 * sizeof(float), // 设置大小
posintions, // 数据
GL_STATIC_DRAW // 使用方式
);
// ! 缓冲区 !
/* --- Draw A Triangle --- */
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
......
}
......
3.2 着色器前传(顶点数据)
顶点数据不仅仅是坐标信息,还包括一系列相关属性:
- 坐标
- 颜色
- 纹理
- 法线
- ......(一切与该点有关的信息)
所以我们不仅要有数据,还得告知 OpenGL 顶点数据的属性布局。
GL 的 API 参考地址。
主要学习 glVertexAttribPointer,glEnableVertexAttribArray
......
/* --- Draw A Triangle --- */
// !数据 !
float posintions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
// !数据 !
// ! 缓冲区 !
......
// ! 缓冲区 !
// !顶点属性布局 !
// 设置某一属性布局
glVertexAttribPointer
(
0, // 属性位置索引,代表第几个属性
2, // 几个数值表示该属性(维度,如位置(x, y)就是二维)
GL_FLOAT, // 数值类型
GL_FALSE, // 是否标准化到 [0,1] (一般是处理颜色时需要)
// 顶点偏移量,某顶点移动到下个顶点所需字节数(仅有位置属性,float x + float y = 2 * 4 = 8 byte)
sizeof(float) * 2,
// 同一属性偏移量,某属性移动到下个同属性所需字节数(单一属性,不用偏移)。
// 如有 0 位置:(float x, float y); 1 法线:float normal,
// 则在取法线时,需要越过位置,即偏移量为 2 * 4 = 8 byte。参数传入(const void*) 8。
0
);
// 启用顶点属性布局
glEnableVertexAttribArray(0); // 给出具体的属性索引
// !顶点属性布局 !
/* --- Draw A Triangle --- */
......

浙公网安备 33010602011771号