OpenGL学习笔记(二)
1. 状态机
OpenGL自身就是一个大型状态机(State Machine),它使用了一种状态模型来追踪所有的OpenGL状态变量。当一个状态值被设置之后,它就一直保持这个状态,直到其他函数对它进行修改为止。
当我们使用glGenBuffer声明buffer并使用glBufferData创建初始化buffer的时候,这个buffer其实是在显存中的,接下来是由GPU而非CPU访问。
而我们调用的OpenGL API,以及以后的shader,其实就是改变OpenGL状态机的状态,通过draw call告诉GPU如何从buffer取数据来进行绘制。
在我看来,这是一种数据-控制模型。
2. 顶点数组与顶点属性
通过声明、创建并初始化vertex array buffer,可以把数据存到到GPU中。
glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(positions) * sizeof(float), positions, GL_STATIC_DRAW);
开启并定义顶点属性
glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, NULL);
在OpenGL中,vertex顶点和vertex position顶点位置是两种概念(因为顶点的位置会随着物体的变化而变化)
顶点还包含
- 纹理
- 坐标
- 法线
- 颜色
- 按法线切线
3. 绘制
最后再在循环中调用glDrawArrays()进行draw call绘制
glDrawArrays(GL_TRIANGLES, 0, 3);
贴上完整代码
#include <GLFW/glfw3.h> int main(void) { GLFWwindow* window; // 初始化GLFW库,对应的需要在退出时候调用glfwTerminate()销毁资源 if (!glfwInit()) return -1; // 创建window和OpenGL context,该window的context需要手动设置成current context window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } // 把window的context设置成current context glfwMakeContextCurrent(window); // 设置顶点的位置 GLfloat positions[] = { -0.5f, -0.5f, 0.0f, 0.5f, 0.5f, -0.5f }; // 用来存储缓冲对象名称 unsigned int VBO; // 生成1个缓冲对象名称,并写到bufferObject glGenBuffers(1, &VBO); // 绑定顶点缓冲到bufferObject glBindBuffer(GL_ARRAY_BUFFER, VBO); // 创建并初始化缓冲对象的数据 glBufferData(GL_ARRAY_BUFFER, sizeof(positions) * sizeof(float), positions, GL_STATIC_DRAW); // 开启顶点着色器的属性,不然无法显示绘制 glEnableVertexAttribArray(0); // 定义顶点数据的属性,其中一个位置有2个浮点数,不需要normalized,步进为sizeof(float)*2字节 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, NULL); // 检查window的关闭标志 while (!glfwWindowShouldClose(window)) { // 清除屏幕颜色 glClear(GL_COLOR_BUFFER_BIT); // draw call,从0开始渲染3个索引 glDrawArrays(GL_TRIANGLES, 0, 3); // 交换window的前后buffer glfwSwapBuffers(window); // 处理事件 glfwPollEvents(); } glfwTerminate(); return 0; }
posted on 2021-05-11 16:33 JacobChen2012 阅读(148) 评论(0) 编辑 收藏 举报