I want to do now is have different arrays and send them to shader, to be able to transform only some arrays, I don't know if this is possible, for the moment I have tried without success, and I was thinking if there is a way to add all the arrays to the same buffer and how to do it.
What you can do is use the same VBO, but only a specified range for each drawing operation. You can use glMapBufferRange to map the VBO from range A to B, pass the data, then make a draw call (glDrawArrays) that only renders from the range A to B. After that, you can map from range B to C and make a draw call that only renders from B to C.
You still have only one VAO. But a VAOs are agnostic, and you can make some trickery with the offsets that will make it work as if it had two layouts:
// Layout 0 for the 3D world
// 3D Pos
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, layout0_stride,
0); // look at the offset
// UV
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, layout0_stride,
4 * sizeof(GLfloat)); // look at the offset
// Layout 1 for the 2D UI
// 2D Pos
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, layout1_stride,
0); // look at the overlapping offset
// UV
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, layout1_stride,
2 * sizeof(GLfloat)); // look at the overlapping offset
This is, of course, an example. It doesn't make much sense to have two layouts just to have a specific layout for 2D drawing. You could use the layout for 3D drawing for that, by simply not using the z component.
After that, you can use an uniform variable in the shader to specify which layout to use. If layout_to_use is 0, then you use the in variables in the layout position 0 and 1. If layout_to_use is 1, then you use the in variables in the layout position 2 and 3:
layout (location = 0) in vec4 in_pos3d;
layout (location = 1) in vec2 in_uv3d;
layout (location = 2) in vec2 in_pos2d;
layout (location = 3) in vec2 in_uv2d;
uniform int layout_to_use;
void main()
{
if (layout_to_use == 0) {
// Do thing with in_pos3d and in_uv3d.
} else if (layout_to_use == 1) {
// Do thing with in_pos2d and in_uv2d.
}
}
When you use the VBO from range A to B, you enable the attribute pointers 0 and 1, and set layout_to_use to 0. When you use the VBO from range B to C, you enable the attribute pointers 2 and 3, and set layout_to_use to 1.
Before doing all that, you should consider if it's worth to add this complexity to your code. Depending on what you are doing, making a single big layout (wasting some bytes) could be a better option.
The other option is using multiple VAOs and multiple VBOs, which has nothing special about but binding each VAO and VBO that you will be using. A costly operation that I don't recommend.