VAO and VBO in Modern OpenGL

I'm going to mention the graphics pipeline of OpenGL in this post. This pipeline consists of certain parts:
  1. Vertex Shader
  2. Tesellations Shader
  3. Geometry Shader
  4. Primitive Assembly
  5. Rasterization
  6. Fragment Shader
  7. Per-sample Operation
We will deal with both Vertex Shader and Fragment Shader mostly. Vertex Shader handles each vertice. Fragment shader handles each pixel color and these shaders have their own special variable.
  • Vertex shader's variable is gl_Position 
  • Fragments shader's variable is fragColor
Vertex shader's called for each vertice. Fragment shader's called for each pixel.

Let's say we have vertices to draw something. These vertices are stored on the CPU. But when we are going to draw something, the related vertices are going to pass to GPU as a buffer. This buffer contains the related vertices about what we want to draw and this buffer is created on the CPU.

Let's create our buffer to draw something. This buffer will contain vertices about two attributes. These attributes are position and color:
self.shader = ShaderProgram("./shaders/vs.glsl", "./shaders/fs.glsl")

data = np.zeros(3, dtype = [ 
                        ("pos", np.float32, 2),
                        ("col", np.float32, 3)
                    ])

data['pos'] = [(-0.5, -0.5), (0.0, +0.5), (+0.5, +0.5)]
data['col'] = [(1,0,0), (0,1,0), (1,1,0)]
Let's create a VAO. Vertex Array Object is array of the VBOs. Vertex Buffer Objects contain the vertex data: 
self.triangleVAO = glGenVertexArrays(1)
glBindVertexArray(self.triangleVAO)

# attrib 0
# loaded vbo'position' to triangleVAO  
positionBuffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer)
glBufferData(GL_ARRAY_BUFFER, data['pos'].nbytes, data['pos'], GL_STATIC_DRAW)

positionLocation = glGetAttribLocation(self.shader.programID, 'position')
glEnableVertexAttribArray(positionLocation)
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 2*sizeof(GLfloat), c_void_p(0))

# attrib 1 
# loaded vbo'color' to triangleVAO
colorBuffer = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer)
glBufferData(GL_ARRAY_BUFFER, data['col'].nbytes, data['col'], GL_STATIC_DRAW)

colorLocation = glGetAttribLocation(self.shader.programID, 'color')
glEnableVertexAttribArray(colorLocation)
glVertexAttribPointer(colorLocation, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), c_void_p(0))

glBindVertexArray(0)
If you notice, GL_ARRAY_BUFFER is actually our bridge to move data from one place to another. We bind the vbo what we load data to GL_ARRAY_BUFFER. And we load the data which in CPU to dataBuffer which is a VBO. These VBOs are introduced by glVertexAttribPointer which is a built-in function in OpenGL.

I run the code and the result should be like this:
gradinet triangle in opengl

According to my view, the VAO is actually an object which can be used as a game object for me. The code above seems complex and if I want to create another VAOs, the code looks terrible obviously. So I'm creating a class that represents VAO:
    def generate(self):
        self.shader = ShaderProgram("./shaders/vs.glsl", "./shaders/fs.glsl")
        self.mesh = Mesh()
        
	...

    def render(self):
        glClearColor(1.0, 1.0, 1.0, 1.0)
        glClear(GL_COLOR_BUFFER_BIT)

        self.shader.use()
        self.mesh.draw()
I just type two methods in Mesh class which are __init__ and draw function. There is no change to the above code. I just pasted these functions into it.

No comments:

Post a Comment