<GeeXLab Rootard Guide/>
Vertex Buffers
Last update: 2018.12.10 by JeGX
>> Back <<
The gh_vb library is used to create and manipulate vertex buffers (vertex buffer) in order to draw a list of vertices in the
form of dots, lines or triangles. Each vertex can have any number of attributes depending on the needs of the demo.
The gh_vb library only handles lists (or arrays) of vertices, it does not support the indexed rendering
(which involves an index buffer as in the gh_mesh library).
gh_vb is a low-level library, but once mastered and wrapped in a higher level interface in Lua or Python, its use becomes easy.
We will now see how to implement it to draw a simple triangle.
Creation of the vertex buffer.
attrib_size = 16 -- vec4 = 16 bytes
num_vertex_attribs = 2 -- position + color
vertex_size = num_vertex_attribs * attrib_size
num_vertices = 3 -- 3 vertices for a triangle
buffer_size = num_vertices * vertex_size
vbid = gh_vb.create(buffer_size, num_vertex_attribs)
Until then, nothing wizard. We have created a vertex buffer to store 3 vertices. Each vertex is composed of a position
(4 float) and a color (4 float too).
More complicated things are starting now. Each vertex attribute must be associated with its corresponding location in
the vertex shader. This is how OpenGL works!
-- Simple vertex color GPU program
local vs_gl3= [[
#version 150
in vec4 Position;
in vec4 Color;
out vec4 v_color;
void main()
{
gl_Position = vec4(Position.xy, 0.0, 1.0);
v_color = Color;
}
]]
local ps_gl3= [[
#version 150
in vec4 v_color;
out vec4 FragColor;
void main()
{
FragColor = v_color;
}
]]
vertex_color_prog = gh_gpu_program.create_v2("vertex_color_prog", vs_gl3, ps_gl3)
gh_gpu_program.bind(vertex_color_prog) -- required for get_vertex_attrib_location()
gh_gpu_program.bind(0)
-- Position attrib
local vertex_attrib_index = 0
local loc = gh_gpu_program.get_vertex_attrib_location(vertex_color_prog, "Position")
local attrib_location = loc
local attrib_type = 1 -- float => 1 ; integer => 2
local dim = 4 -- vec4
local stride = vertex_size -- 16 bytes
local offset = 0 -- position
gh_vb.set_vertex_attrib_data(vbid, vertex_attrib_index, attrib_location, attrib_type, dim, stride, offset)
-- Color attrib
vertex_attrib_index = 1
loc = gh_gpu_program.get_vertex_attrib_location(vertex_color_prog, "Color")
attrib_location = loc
attrib_type = 1 -- float => 1 ; integer => 2
dim = 4 -- vec4
stride = vertex_size
offset = attrib_size -- color
gh_vb.set_vertex_attrib_data(vbid, vertex_attrib_index, attrib_location, attrib_type, dim, stride, offset)
That's it, the most complicated part is over. This part should be hidden in a higher level function (in Lua / Python).
We just have to fill the vertex buffer with positions and colors.
First you have to make the vertex buffer accessible to the CPU (the mapping) so you can write in:
gh_vb.map(vbid, "GL_WRITE_ONLY")
The first vertex (bottom left) with a red color:
-- position vertex 0
local buffer_offset_bytes = 0
gh_vb.set_value_4f(vbid, buffer_offset_bytes, -1, -1, 0, 1)
-- color vertex 0
buffer_offset_bytes = buffer_offset_bytes + attrib_size
gh_vb.set_value_4f(vbid, buffer_offset_bytes, 1.0, 0.0, 0.0, 1.0)
The second vertex (in the middle and at the top) with a green color:
-- position vertex 1
buffer_offset_bytes = buffer_offset_bytes + attrib_size
gh_vb.set_value_4f(vbid, buffer_offset_bytes, 0, 1, 0, 1)
-- color vertex 1
buffer_offset_bytes = buffer_offset_bytes + attrib_size
gh_vb.set_value_4f(vbid, buffer_offset_bytes, 0.0, 1.0, 0.0, 1.0)
The third vertex (bottom right) with a blue color:
-- position vertex 2
buffer_offset_bytes = buffer_offset_bytes + attrib_size
gh_vb.set_value_4f(vbid, buffer_offset_bytes, 1, -1, 0, 1)
-- color vertex 2
buffer_offset_bytes = buffer_offset_bytes + attrib_size
gh_vb.set_value_4f(vbid, buffer_offset_bytes, 0.0, 0.0, 1.0, 1.0)
Now that the data is written, we can disable unmapper the vertex buffer:
gh_vb.unmap(vbid)
That's it, our vertex buffer is created and initialized. We now draw it.
We start by activating (or binding) the GPU program:
gh_gpu_program.bind(vertex_color_prog)
Once the GPU program is activated/bound, we can draw the vertex buffer:
gh_vb.bind(vbid)
local LINE_DEFAULT = 0
local LINE_STRIP = 1
local LINE_LOOP = 2
gh_vb.draw_lines(vbid, 3, 0, LINE_LOOP)
gh_vb.unbind(vbid)
The result in GeeXLab:
It is also possible to draw points:
gh_vb.bind(vbid)
gh_vb.draw_points(vbid, 3, 0)
gh_vb.unbind(vbid)
Or triangles:
gh_vb.bind(vbid)
local TRIANGLE = 0
local TRIANGLE_STRIP = 1
local TRIANGLE_FAN = 9
triangle_mode = TRIANGLE_FAN
gh_vb.draw_triangles(vbid, num_vertices, 0, triangle_mode)
gh_vb.unbind(vbid)