Greetings fellow OpenGL enthusiasts!
Now let's begin.
public class Loader {
public void createVAO(int[] indices) {
int vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
createIndicesVBO(indices);
glEnableVertexAttribArray(0);
}
public void createVBO(float[] vertices) {
int vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = makeByteBufferFromArrayOfFloats(vertices);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
}
public void createIndicesVBO(int[] indices) {
int vboID = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboID);
IntBuffer buffer = makeByteBufferFromArrayOfInts(indices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
}
public void pleaseDraw(float[] vertices, int[] indices) {
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);
}
public void cleanUp() {
glDeleteBuffers(0);
glDeleteVertexArrays(0);
}
public FloatBuffer makeByteBufferFromArrayOfFloats(float[] vertices) {
FloatBuffer FloatByteBuffer = BufferUtils.createFloatBuffer(vertices.length);
FloatByteBuffer.put(vertices);
FloatByteBuffer.flip();
return FloatByteBuffer;
}
public IntBuffer makeByteBufferFromArrayOfInts(int[] array) {
IntBuffer IntByteBuffer = BufferUtils.createIntBuffer(array.length);
IntByteBuffer.put(array);
IntByteBuffer.flip();
return IntByteBuffer;
}
}
Note - This code is working and outputs a blue window with a black quad in the middle. Questions:
glBindBuffer(GL_ARRAY_BUFFER, vboID);
I don't understand clearly what does GL_Array Buffer even means. As far as I can get it just shows to OpenGL current state that this VBO will store Array data at some point. But from the function below I can guess that it is not just a type of data but it is like a
container for a data and this is only that can be active for a current state. Am I getting it right? Or am I missing something? glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
Again this GL_Array_Thing. And it seems this funtion puts a data into GPU or It puts current VBO into VAO? I'm not sure.glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
So VAO consist of attributes and here we show to OpenGL how to read our 0 attrib. Correct me if I'm wrong.glEnableVertexAttribArray(0);
and glVertexAttribPointer(0, 3, GL_FLOAT, false, 0,0);
to glEnableVertexAttribArray(1);
and glVertexAttribPointer(1, 3, GL_FLOAT, false, 0,0);
. Nothing should change in final render, but in reality black quad is not appearing. Can't figure out why.glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_INT,0);
There are a lot of extra questions but they either appears because of my lack of understanding about questions that I described above. Please help me to make out this mess in my head about fundamentals of OpenGL. For those who were able to read or even answer to this post - Thanks a lot!
glBindBuffer(GL_ARRAY_BUFFER, vboID);
Means: I have several VBOs. Select (for next usage) the one identified by vboID
. The mode GL_ARRAY_BUFFER
is for raw (bytes) data.
glBufferData(GL_ARRAY_BUFFER, size, buffer, GL_STATIC_DRAW); //Notice I added "size" for C++. LWJGL doesn't need it.
Means: Fill currently bound array_buffer (with "glBindBuffer") with size
bytes; take them from buffer
(an address in CPU RAM). My intention (GL_STATIC_DRAW
) is that the GPU reads many times the data, not to modify it.
glVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0,0); // "stride" added
The GPU reads from one or several VBOs. For example the VBO may consists of x,y,z coords (3 floats) followed by R,G,B,A color-components (4 bytes) and repeat the sequence for other vertices.
glVertexAttribPointer establish the relation between VBO and the attributes needed. In the example: the first attribute (0
) needs 3
values of type GL_FLOAT
which are not(false
) normalized (not in [0.0, 1.0] range). The next sequence for this attribute is stride
bytes far (using 0 means attributes are tightly packed). The last 0.0
is the offset in the VBO for the first attribute.
The color may be read as another attribute, from the same VBO or not. The "name" for this attribute may be 1
, because 0
is already used for coordinates. So it needs its own glVertexAttribPointer
call.
The attribute identifiers were chosen by the GPU. Since OpenGL >=3.3 (which I strongly advise to use) you better choose them (by "location = 0" stuff in the shaders)
A VAO
contains the buffers bindings and the attributes bindings. Each time you need to render the data from some VBOs you don't need to use again the glBindBuffer
and glVertexAttribPointer
required. Just use glBindVertexArray
instead.
"Indexing rendering" means that you use two VBOs: one for coordinates and the other for indices. (Other VBOs may also be used for other attributes). The VBO with indices tells the GPU the "sequences" order from the first VBO (and the other VBOs). These allows to read the same vertex several times without repeating its attributes. Notice that a triangulation shares the same vertex among several triangles. You can avoid sending to GPU repeated data.