(由于又莫名同时使用了“绑定”和“注册”的说法,所以认为同义)
-
VBO+LVA部分工作流
(有时也记作BO+LVA)
VBO工作流
float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; //NDC,用[-1,1]映射到窗口长宽。这里的D是Device即设备,“窗口是一个设备”的表述还算有点印象。 //窗口句柄好像也就是设备上下文。。。 //NDC将在Viewport Trans中转为SSC,这步发生在Rasterization。 unsigned int VBO; glGenBuffers(1, &VBO);//GLsizei、GLuint*类型 glBindBuffer(GL_ARRAY_BUFFER, VBO);//GLenum、GLuint类型 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//GLsizeiptr类型 //glGetActiveAttrib //glfwSetCharCallback //glBindBuffer(GL_ARRAY_BUFFER, 0),“back to default”。 //OpenGL中的对象具有的函数通常有glGen、glBind、gl...Data、glSet(可选)。 //常用的参数类型中,GLuint*是为了传出值到函数作用域外(典型C风格),并且也说明了可以是数组。 //GLenum起到各种hints的作用,都是以GL_开头的宏。 //GLsizei是要创建的Object的个数,个数大于1时传出到GLuint*是一个数组名。 //GLsizeiptr是“ptr的GLsizei”。这里的ptr是以常指针方式传入的外界数组,所以该参数要求的是传入数组的大小。 //ptr通常是const void*或者const GLvoid*。 //从这里可以知道用来与OpenGL直接交互的数据类型全都必须是C风格的! //GL_STATIC_DRAW是三种缓冲区标记之一,用于写一次读多次的缓冲区。记忆:生成、绑定/解绑、配置数据
Link Vertex Attributes工作流
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); //VBO虽然通常认为是连续的一片内存空间,但是: //1. 它首先分为不同的顶点数据集,如位置、颜色…… //2. 每个数据集又由固定大小的数据组成,如位置数据集中,每个点的位置都是一个浮点向量。 //因此通过第一个参数GLuint index确定是哪个数据集 //第二个参数GLint size是确定每个数据是几维向量,第三个是为确定分量类型 //第五个GLsizei stride和第六个GLvoid* offset共同确定数据集的组成方式:从offset开始每隔stride个数据取一个 //第四个数据用于确定是否标准化,[-1,1]或[0,1]。 //glVertexAttribPointer()提供给shader解释VBO数据的方法,这是必须的,与EBO无关,因此一定要有且最好和VBO写一起。 //glEnableVertexAttribArray(GLuint index)和glDisableVertexAttribArray(GLuint index)分别控制第index个VAA的启用与否。记忆:切片注册、启用/禁用
最后使用
glDrawArrays(GLenum mode,GLint,GLsizei)绘制。第一个参数是要绘制的图元,通过后两个参数begin+size切片。
(Link时的切片是begin+interval切片)
-
EBO部分工作流
//前文注册VBO到OpenGL。 unsigned int indices[] = { 0,1,2, 1,2,3 }; unsigned int EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); //除了EBO会被注册到GL_ELEMENT_ARRAY_BUFFER这个不同的属性之外,其他步骤一样。最后使用
glDrawElements(GLenum mode,GLsizei,GLenum type,const GLvoid*)绘制。主要区别是在前文绑定EBO时,通过第二和第四个参数实现begin+size切片。
或者未绑定EBO时通过第三和第四个参数在调用该函数时传入EBO,此时只能实现size切片。
-
VAO部分工作流
(VAO+BO+EBO【可选】+LVA)
unsigned int VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); //绑定VAO后,VBO、EBO将会绑定在OpenGL的VAO上 float vertices[] = { -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f }; unsigned int VBO; glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); unsigned int indices[] = { 0,1,2, 1,2,3 }; unsigned int EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); //在VAO中有VBO、EBO、VAA //实际上是记录了glBindBuffer、glBufferData、glVertexAttribPointer、glEnableVertexAttribArray的运行。 glBindVertexArray(0); //解绑后,VAO就不会被意外修改了。记忆:生成、绑定/解绑、配置数据
配置通过记录后文完成。
-
EBO绑定在VAO上的,所以不能在配置数据时解绑EBO;而VBO通过VAP()转化成VAA绑定在VAO上,在配置数据末期可以解绑VBO。
-
如果render loop中绘制函数发现OpenGL中没有VAO,core版本规则是不进行任何绘制。
-
comment 评论区
star_outline 咱快来抢个沙发吧!