三、OpenGL 简单开始 --- 简单三角形绘制(vertex buffer & shader pre)

上一篇:二、OpenGL 简单开始 --- 从“规范”到“调用”

下一篇:四、OpenGL 简单开始 --- 着色器(shader)

1. 缓冲区 和 着色器

简单介绍:

  • C++ 程序在 CPU 运行,缓冲区存放 CPU 给 GPU 的数据
  • 着色器是在 GPU 运行的程序,通过 drawcall 取缓冲区数据利用 GPU 进行渲染。

2. OpenGL 工作模式是个 “状态机”

工作模式:你告诉他,用什么缓冲区(定义的),用哪个着色器(GPU 内的),绘制什么样的三角形(图形数据),然后他帮你完成。

  • 缓冲区:定义大小、编号;
  • 着色器:如何读取数据(告诉 OpenGL 数据布局),使用数据;
  • 数据:图形数据,存入缓存。

2.1 状态机概念

image

  • 状态机(State Machine)是有限状态自动机的简称,是现实事物运行规则抽象而成的一个数学模型。
  • 状态(State),现实事物是有不同状态的,例如自动门,有 openclosed 两种状态。有限状态机,即被描述的事物状态数量有限个,例如自动门状态是两个 open 和 closed。
  • 事件 (Event),执行某个操作的触发条件或者口令。对于自动门,“人接近和远离”就是事件。
  • 动作 (Action),事件发生以后要执行动作。例如事件“人接近”,动作是“开门”;编程的时候,一个 Action 一般就对应一个函数。
  • 变换 (Transition),也就是从一个状态变化为另一个状态。例如“开门过程”就是一个变换。

这样看,我们利用 GLEW 使用 OpenGL 的时候,编写的都是事件 Event 指令OpenGL 负责通过指令,进行工作状态的转换,调用 GPU 上实现的函数 Action

3. 代码参考

3.1 数据 和 缓冲区

GL 的 API 参考地址
主要学习 glGenBuffersglBindBufferglBufferData
缓冲区数据的使用方式的参考如下:

image

 ......
 /* --- 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 参考地址
主要学习 glVertexAttribPointerglEnableVertexAttribArray

......
 /* --- 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 --- */
 ......
posted @ 2024-05-08 13:12  bok_tech  阅读(43)  评论(0)    收藏  举报