OpenGL-顶点着色器
顶点
顶点用于图元装配,OpenGL支持的图元有三种:点、线、三角形,对于点只需要一个顶点,对于三角形需要三个顶点。
1 | float vertices[] = { |
顶点坐标
OpenGL不是简单的把所有的3D坐标变换成屏幕上的2D像素,仅当3D坐标在3个轴上-1.0到1.0的范围内时才处理它,所有在这个范围内的坐标叫做标准化
(0,0)是坐标的中心,y轴正方向向上,x轴正方向向右。
VBO(Vertex Buffer Objects)
将顶点数据作为输入发送给顶点着色器后,它会在GPU上创建一块内存用于存储顶点数据。使用顶点缓冲对象可以用来管理这块内存,用缓冲对象可以一次性的发送大量数据到GPU上,CPU到GPU的传输比较慢,所以尽量一次性发送尽可能多的数据。
使用glGenBuffers函数生成一个缓冲对象
1 | unsigned int VBO; |
OpenGL有很多缓冲对象类型,顶点缓冲对象的类型是GL_ARRAY_BUFFER,OpenGL允许同时绑定多个缓冲,但是缓存类型不能相同,使用glBindBuffer将创建的缓存对象绑定到GL_ARRAY_BUFFER上。
1 | glBindBuffer(GL_ARRAY_BUFFER, VBO); |
绑定之后,任何针对GL_ARRAY_BUFFER的缓存配置都会作用到绑定的缓冲对象上,使用glBufferData函数可以将顶点数据复制到缓对象管理的内存中。如果缓冲中的数据会频繁变化,需要使用GL_DYNAMIC_DRAW,这样GPU会把数据放在能够高速写入的内存部分。
1 | // GL_STATIC_DRAW: 数据不会或几乎不会改变 |
链接顶点属性
通过VBO上传了顶点数据,编写了顶点着色器后,需要将顶点数据链接到着色器中的in属性上,通过glVertexAttribPointer将当前绑定到GL_ARRAY_BUFFER类型上的VBO中的数据链接到对应位置的顶点in属性上。
1 | // 0: in属性location |
VAO(Vertex Array Object)
如果有多个顶点属性需要配置,可以使用顶点数组对象,顶点数组对象可以像顶点缓冲对象那边被绑定,可以将多个顶点属性的配置都绑定到VAO上,这样只需要配置一次,切glVertexAttribPointer换不同的属性配置时只需要绑定不同的VAO即可。
创建VAO
1 | unsigned int VAO; |
绑定VAO,当绑定VAO后,后面调用glVertexAttribPointer对顶点属性进行的配置都会自动存储到VAO中。
1 | glBindVertexArray(VAO); |
EBO(Element Buffer Object)
元素缓冲对象也叫索引缓冲对象。EBO是一个缓冲区,和VBO一样,存储OpenGL用来决定要绘制哪些顶点的索引,索引定义了顶点的组合方式,顶点可以重复使用。
1 | float vertices[] = { |
创建EBO
1 | unsigned int EBO; |
EBO的类型是GL_ELEMENT_ARRAY_BUFFER,使用glBindBuffer将创建的缓存对象绑定到GL_ELEMENT_ARRAY_BUFFER上。
1 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); |
绑定之后,任何针对GL_ELEMENT_ARRAY_BUFFER的缓存配置都会作用到绑定的缓冲对象上,使用glBufferData函数可以将索引数据复制到缓对象管理的内存中。如果缓冲中的数据会频繁变化,需要使用GL_DYNAMIC_DRAW,这样GPU会把数据放在能够高速写入的内存部分。
1 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); |
使用EBO后,需要用glDrawElements替换glDrawArrays。
1 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); |
EBO也可以绑定到VAO中,只需绑定一次,后续只绑定VAO即可。
顶点着色器(Vertex Shader)
图形渲染管线的第一部分是顶点着色器,着色器可以看成是一个纯函数,输入的所有顶点,都会依次执行该函数,在该函数中对输入的顶点进行处理,然后输出新的顶点位置。
1 |
|
顶点坐标
顶点着色器中通过定义in变量来接收外部定义的顶点数据,通过glVertexAttribPointer将VBO数据绑定到aPos变量上,这个输入的顶点都会依次执行该着色器函数,通过定义一个uniform的矩阵变量可以实时对顶点坐标进行变换。gl_Position输出最终变换过的顶点坐标。
纹理坐标
通过顶点着色器传递纹理坐标给片段着色器,可在光栅化时对坐标进行片段插值。