I use old way to provide the data to vertex buffer in OpenGL
glGenBuffers(1, buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pos), pos, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
Since OpenGL 4.3 there a new slightly more clear way to provide data to vertex shader appears
const GLfloat colors[] =
{
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
glBindVertexBuffer(1, buffer, 0, 3 * sizeof(GLfloat));
glVertexAttribFormat(1, 3, GL_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(1, 1);
glEnableVertexAttribArray(1);
but I can't find any resources explaining how to provide data using new way. Of course I can do like this
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); //i can do even so, and later I can use glBindVertexBuffer
but it looks not really elegant. If I will not use glBindBuffer and only use glBindVertexBuffer and then use glBufferData, I'll overwrite data in buffer that was bind using glBindBuffer.
So question is: can I provide data to vertex buffer other way or I should always use glBindBuffer, glBufferData and only after that use glBindVertexBuffer, glVertexBufferFormat, glVertexAttribFormat and glVertexAttribBinding. Thank you!
From what I can tell from the OpenGL 4.3 specification, you will still need to bind the vertex buffer to a "regular" binding point in order to update its data:
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferSubData(GL_ARRAY_BUFFER, offset, size, data);
This problem has effectively been solved in the 4.5 specification with the introduction of DSA functions, which allow you to update the buffer data without binding it to a slot first:
glNamedBufferSubData(buffer, offset, size, data);
glVertexAttribFormat and glVertexAttribBinding are telling OpenGL how the data is organized in the buffer; essentially they replace glVertexAttribPointer (and only glVertexAttribPointer). Loading the data still happens with glBuffer[Sub]Data.
Related
I read two demos about 'Getting started with OpenGL'
Google Android hello-gl2
gl_code.cpp
learnopengl.com Hello-Triangle
hello_triangle.cpp
For the last parameter of glVertexAttribPointer :
google android demo : use array name gTriangleVertices
learnOpenGL.com demo : use 0.
google android demo :
glUseProgram(gProgram);
checkGlError("glUseProgram");
glVertexAttribPointer(gvPositionHandle, 2,
GL_FLOAT, GL_FALSE, 0,
gTriangleVertices); // array name
checkGlError("glVertexAttribPointer");
glEnableVertexAttribArray(gvPositionHandle);
learnOpenGL.com code segment :
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
-0.5f, -0.5f, 0.0f, // left
0.5f, -0.5f, 0.0f, // right
0.0f, 0.5f, 0.0f // top
};
unsigned int VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3,
GL_FLOAT, GL_FALSE,
3 * sizeof(float),
(void*)0); // my question : `0`
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
click : code comparision screenshot
I tend to think that learnOpenGL's demo is wrong,
but learnOpenGL is a well-known website, it's impossible to make mistakes.
Finally , both demos can display triangle correctly.
I'm confused.
I'm confused about when to pass 0 and when to pass the pointer value ?
The last parameter of glVertexAttribPointer has the type const void * for reasons of compatibility.
If a non-zero named buffer object is bound to the GL_ARRAY_BUFFER target, the last argument (pointer) is treated as a byte offset into the buffer object's data store:
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), (void*)0);
In legacy OpenGL (compatibility profile OpenGL Context) it is possible to specify a data pointer directly (in this case it must not be bound a buffer object, because the pointer should not be treated as a byte offset into the buffer):
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), gTriangleVertices);
However, there is more. See glVertexAttribPointer and glVertexAttribFormat: What's the difference?
I have recently embarked on learning OpenGL for 3d graphics from this website. I understand that there are some very old tutorials out there for this library since it has been around for a long time. Most tutorials use the commands glBegin() and glEnd() to draw shapes. This is very simple and easy to follow in my opinion.
However, it has come to my understanding that this is supposedly outdated and I should be using glDrawArraysinstead. The problem is this, I just don't understand the code/concepts that are needed to draw using this method. The code is as follows:
void draw() {
//i get this bit
static const GLfloat g_vertex_buffer_data[] = {
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
};
//I stop getting it here
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
}
Could somebody explain this code line by line and maybe explain the concept behind a buffer. Also, I'm curious, do the old draw commands still work in new versions and if so, is it bad practice to use them?
Please explain everything in as simple language as possible, I'm a complete beginner in this subject. TBH, I dont even know what a buffer is.
I'll explain this on my simple understanding, so some probably going to be wrong.
The old function is deprecated which is like removed/discouraged from using, but it is still there to support backward compatibility. You can read about it here. As far as i know, the old deprecated function is not present in OpenGL ES or WebGL.
You can say buffer object is an OpenGL object that store/allocate memory to store data in the gpu. You can read about it here
glGenBuffers(1, &vertexbuffer);
Generate/create a new buffer. It will assign vertexbuffer with a number which you can use to access the buffer.
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
Start using (bind) the buffer vertexbuffer
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
Allocate memory and set the data for the binded buffer. GL_STATIC_DRAW, GL_DYNAMIC_DRAW, GL_STREAM_DRAW will tell the gpu where to store the memory for the best performance.
glEnableVertexAttribArray(0);
This tell the gpu to start using the attribute located at 0. If you're using a shader you can get it with GLint glGetAttribLocation(GLuint program, const GLchar *name); link
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
Binded it two times, doesn't do anything much. Except you unbind it somewhere else or bind other buffer.
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
This is to set how the attribute located at 0 is going to be used. This means the attribute is going to be used like: for every vertex, there is 3 floats variable that doesn't need to be normalized which is tightly packed (stride = 0, offset = 0).
P.s: shouldn't the stride be 3 * sizeof(GLfloat)? Edit: nvm, according to this it should be fine.
Edit: According to #Nicol Bolas:
it stores the buffer object that was bound to GL_ARRAY_BUFFER at the time the function was called.
Edit:
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer);. Example:
For the position it would be like glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*) (0 * sizeof(GLfloat)));
For the texture coord it would be like glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*) (3 * sizeof(GLfloat)));
For the color it would be like glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*) (5 * sizeof(GLfloat)));
This is assuming your shader has the location for position at 0, for texture coord at 1, and at 2 for color attribute.
glDrawArrays(GL_TRIANGLES, 0, 3);
Tell the gpu to draw a triangles using 3 vertex with offset 0 from the binded vertex buffer (vertexbuffer).
glDisableVertexAttribArray(0);
Stop using the attribute located at 0.
Vertex Array Object:
GLuint VertexArrayID;
This is the same as vertexbuffer from before, it store the id to access it.
glGenVertexArrays(1, &VertexArrayID);
Same as before too, this generate/create a new vertex array.
glBindVertexArray(VertexArrayID);
Same as before, start using/bind the vertex array.
Now the explanations about vao begin. Basically this object will remember the vbo (can be multiple) and how does it going to be used (from glVertexAttribPointer()), this only needed to be set once. When you're not using vao, each time you unbind and bind the vbo you need to set the attribute again. By using vao you only need to bind the vao as simple as calling glBindVertexArray(GLuint vaoID); and it will do everything for you which help a lot. So, you don't need to bind the vbo, set the attribute, and everything else. Instead just bind the vao, draw, unbind the vao, and done.
Sorry for the long and not perfect explanation.
Hi so i have been basically pulling my hair out trying to understand this OpenGL confusion
i have tried to find answers in books, in tutorials , and even experimenting around with it
SO basically i have a opengl program that draws the first time my two triangles, however when i try to redraw the first triangle again it doesnt seem to be working
i dont know what information i am missing , but its no t making any sense
as far as i understand once the VAO and VBO have been created and bounded and buffered to memory, and vertex attrib pointers set and enabled that once i bind the vao object that i want to draw as many times as i like, i just have to do that
after initialization which works for me, the problem is that once i rebind another vao object it doesnt seem to draw it
my code is quiet long , i can paste it here if you like, but i think that the drawing part of the code would be sufficient
here it is
GLfloat vec[] = {0.0f, 0.0f,
1.0f, -1.0f,
-1.0f, -1.0f};
GLfloat vec2[] = {0.0f, 1.0f,
1.0f, 0.0f,
-1.0f, 0.0f};
//next step is to upload data to graphics memory
//generating a buffer from openGL
GLuint vbo;
GLuint vbo2 ;
GLuint vao;
GLuint vao2;
glGenBuffers(1, &vbo);
glGenBuffers(1, &vbo2);
glGenVertexArrays(1, &vao);
glGenVertexArrays(1, &vao2);
//to upload the actual data must make the object active by binding it to a target
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//upload the data of active object to memory
glBufferData(GL_ARRAY_BUFFER, sizeof(vec), vec, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vec2), vec2, GL_STATIC_DRAW);
//bind and draw
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays (GL_TRIANGLES, 0, 3);
glXSwapBuffers ( dpy, glxWin );
sleep(3);
glClear(GL_COLOR_BUFFER_BIT);
//rendering second triangle
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
glBindVertexArray(vao2);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays (GL_TRIANGLES, 0, 3);
glXSwapBuffers ( dpy, glxWin );
sleep(3);
//rendering the first triangle again------where the problem lies!!!
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,2,GL_FLOAT, GL_FALSE, 0, NULL);
glDrawArrays (GL_TRIANGLES, 0, 3);
glXSwapBuffers ( dpy, glxWin );
sleep(3);
You'll also need to clear the depth buffer glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
If you follow a tutorial then you will probably have enabled depth testing in the openGL setup boilerplate it provided. This is because more people will want to use the depth buffer than not.
you can also not call glEnable(GL_DEPTH_TEST); during setup.
I've been having a problem recently when getting to grips with Opengl VAOs.
Currently I have code which draws a triangle from a array of floats using a VBO.
Here is the code.
float vpp[] = { 0.75f, 0.75f, 0.0f,
0.75f, -0.75f, 0.0f,
-0.75f, -0.75f, 0.0f};
// Non Indexed
glGenBuffers(1, &m_mainVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_mainVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vpp), vpp, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_POINTS, 0, 3);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Now when I try to implement a VAO, the program only draws out 1 point. (I would post a screen cap but I can't).
And the code for this one.
float vp[] = { 0.0f, 0.75f, -0.75f };
//VAO
unsigned short sInds[9] = { 1, 1, 0,
1, 2, 0,
2, 2, 0};
//Indexed
glGenBuffers(1, &m_mainVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_mainVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vp), vp, GL_STATIC_DRAW);
GLuint elBuf;
glGenBuffers(1, &elBuf);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 9 * sizeof(unsigned short), sInds, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawElements(GL_POINTS, 3, GL_UNSIGNED_SHORT, sInds);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Can anyone show me what I'm doing wrong?
Your code is broken, and that has nothing to do with your "VAO" (or as Datenwolf pointed out, your lack of a VAO).
You don't seem to understand what the index in the index buffer actually does. You defined attribute 0 to be an array of 3 floating-point values. In C terms, you said, float attrib0[numberOfPositions][3];. When OpenGL sees the first index, it will fetch three values from the array. It will fetch:
attrib0[index][0];
attrib0index;
attrib0[index][2];
Your index is a vertex index, not a GL_FLOAT index. The array elements are 3 floats each, not 1 float each.
What you're trying to do is not really possible or useful. And as Datenwolf pointed out, it has nothing to do with VAOs (since your code doesn't use them). You're talking about indexed rendering, which is a different topic from VAOs.
Which OpenGL version do you use? So far your code uses only Vertex Buffer Objects, but there's no Vertex Array Object support code there, yet. If you're on OpenGL-4 core, you need to create a VAO first, otherwise nothing will draw.
If you don't plan on using VAO abstraction, you can create a catch-all VAO right after creation of the context.
GLuint vaoID;
glGenVertexArrays(1, &vaoID);
glBindVertexArray(vaoID);
Update:
I didn't it notice yesterday night, but Nicol Bolas did. Some part of your second code snippet doesn't make sense. vp defines only 3 floats. It now completely depends on the semantics of the vertex shader (using generic vertex attributes mandates the use of shaders) how these are to be interpreted. Your call of glVertexAttribPointer with a element size of 3 tells OpenGL, that each element of that vertex attribute has 3 fields, which are addressed together.
float vp[] = { 0.0f, 0.75f, -0.75f };
\------------------/ one attribute element
It would make more sense with your first definition vpp
float vpp[] = { 0.75f, 0.75f, 0.0f,
\----------------/ attribute element 0
0.75f, -0.75f, 0.0f,
\-----------------/ attribute element 1
-0.75f, -0.75f, 0.0f};
\------------------/ attribute element 2
If you enable several vertex attributes, they together form a long vector of several attributes.
The indices supplied to glDrawElements address such vertex attribute vectors, not their individual fields.
I'm trying to draw a quad for a background (2D) using OpenGL 3.x+. Quads are deprecated, so the goal is to use two triangles to make a rectangle that fills the screen. It's working, but I'm not 100% clear on everything here.
Setup
GLuint positionBufferObject;
GLfloat vertexPositions[] =
{
-1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 1.0f,
};
glGenBuffers(1, &positionBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
I understand the vertexPositions, it's an array of vertices.
glGenBuffers() is saying, I want 1 buffer and assign id to &positionBufferObject?
glBufferData() uploads the vertexPositions to the GPU's memory; but how does it know were to upload it since I didn't give it an ID?
Draw
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
glDisableVertexAttribArray(0);
glEnableVertexAttribArray() just says I'm going to be drawing with array 0?
glDrawArrays() - what if I want to draw two vertex arrays? How does it know which ones to render? It knows that from the above command?
Not sure what glVertexAttribPointer() does?
glDrawArrays() is clear.
Clean up, I think this is right?
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &positionBufferObject);
I only do the setup/cleanup once.
Bonus points:
Is this the most effective way to render this? I read that I'm suppose to be submitting and be rendering in "batches" [?] since 3.x+ doesn't do immediate mode any more. There is also only one array, so batches won't help performance in this case, but if I had say "a very large number" of vertxArrays to draw, would it be the same process?
In setup they are storing the array id as positionBufferObject, but have it hardcoded in the rendering loop. Seems like it would get confusing after a dozen or so arrays, why isn't it good practice to use the variable instead of hardcode it?
glGenBuffers(1, &positionBufferObject); says "make a vertex buffer object, and positionBufferObject is its ID."
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject); says "positionBufferObject is now the current GL_ARRAY_BUFFER."
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW); says "upload vertexPositions to the ID currently bound to GL_ARRAY_BUFFER (which is positionBufferObject)."
glEnableVertexAttribArray(0); says "vertex attribute array 0 is now available for use."
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); says "vertex attribute array 0 is to be interpreted as consisting of groups of 4 floats."
glDrawArrays(GL_TRIANGLE_STRIP, 0, 5); says "draw a triangle strip with five indices from every enabled array."
glDisableVertexAttribArray(0); says "we're done for the time being with vertex attribute array 0."
In answer to user697111's question about multiple arrays, it's quite simple.
Each vertex attribute needs to be associated with a buffer object. Rather than specifying the buffer object with glVertexAttribPointer, the association is done through GL_ARRAY_BUFFER. When you call glVertexAttribPointer (or any gl*Pointer call), the buffer that is currently bound to GL_ARRAY_BUFFER will be used as the source for that attribute. So, consider the following:
glBindBuffer(GL_ARRAY_BUFFER, myPositionData);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, ..., 0);
glBindBuffer(GL_ARRAY_BUFFER, myColorData);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, ..., 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDrawArrays(...);
Attribute 0 will come from the buffer object myPositionData, and attribute 1 will come from the buffer object myColorData. The fact that I undid the binding to GL_ARRAY_BUFFER before calling glDrawArrays does not change where the data for those attributes comes from.