Also important to note that Index Buffer / ELEMENT_ARRAY_BUFFER is also contained within VAO state. It does not need to be redefined per-frame... so you can also remove that line, too. The GL_ELEMENT_ARRAY_BUFFER has to be bound after the vertex array object has been bound (glBindVertexArray). The GL_ELEMENT_ARRAY_BUFFER object is stored in the vertex array objects state vector. If the vertex array object has been unbound and is bound again, then the GL_ELEMENT_ARRAY_BUFFER is known and bound again too. But if the element array buffer explicitly gets unbound while the vertex array object is bound, it is removed form the state vector.
15:10 The two options can be stated simply: (A) `COMPAT_PROFILE` means recycling one default/global VAO for everything; this is the default profile for backward-compatibility. (B) `CORE_PROFILE` means defining as many VAOs as you like. Changing VAOs is fewer-calls/optimal/easier/faster than otherwise changing the VAAs + VBOs + IBs many times per frame.
@@rafaelfernandes4432 Are you binding your index buffer while you still have your vertex array binded? It worked for me, I'm not sure how it would be different for you.
11:33 you dont need to bind index buffer at all if you bound your vertex array object because vertex array object contain all of it(vertex buffer & index buffer)
I was thinking this as well, but if you switch some lines around - specifically, unbinding the IBO before you unbind the VAO - you'll get a debugbreak at DrawElements(); Anyone knows what's going on beneath the surface here? I say this because if you switch other binds around (for instance, unbinding shader, VBO - or even both - before unbinding the VAO), it will still work, whereas with the IBO it will not.
@@gabrieleboas1129 I've thought about it, and I'm 99% sure that all changes (binding or unbinding) in a vertex buffer, index buffer, or vertex attribute are saved in the bound vertex array. That means that while VAO is bound, IBO being unbound will be saved in the vertex array. I assume this is also why Cherno initialized the vertex array before either the vertex buffer, or index buffer. Once a vertex array is unbound, it's basically inactive.
@@gabrieleboas1129 Im pretty sure that a VAO can only have 1 index buffer and so as soon as he bound it to his VAO, that state was saved and so you don't need to keep rebinding it but if you were to bind GL_ELEMENT_ARRAY_BUFFER to 0 then no buffer would be bound and would probably generate error but im not completely sure
@@elijahvillarmia7742 Vertex Arrays and Index Buffers are 2 entirely different but related pieces of data to OpenGL. A Vertex Array is the actual data used to construct the geometry, whereas an Index Buffer is the instructions on which order it all gets sent to the vertex shader. They are bound separately, and any Index Buffer can be used with any Vertex Array, provided you don't get an out of bounds error with said combination. Another note is that Index Buffers apply to every attribute array in the Vertex Array. So if you've got UV coordinates and normals in there along with vertex positions, a 0 in the Index Buffer means the first vertex position, with the first UV, and the first normal, all get sent to the vertex shader as that "vertex"
I realize this is more of a GL 4.3+ approach, but you could create VAO objects for different purposes (types of models, shaders, etc.) that are re-usable. While setting up the VAO, use the stateless glVertexAttribBinding and glVertexAttribFormat functions that don't bind to a VBO. Then simply bind the appropriate VAO before drawing, bind the VBO using glBindVertexBuffer, bind to the element buffer using glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...), and do your drawing.
Would love to hear more about your day job. Did you have a mentor at EA who taught you a lot of this stuff or are you completely self taught? How do you choose the technology that goes into your games for the high end products? Maybe this is for your vlog, but I think it would be interesting.
Thank you very much! Even after reading numerous of opengl pages for VAO, VBO etc.. your videos made them totally clear to me! I mean why is so hard for Khronos to give good explanations!!!! Thanks again!
For anyone who didn't specify a shader at this point: I skipped the shaders part, followed every tutorial except for shaders, so up to now I just got a white rectangle. When using core, I didn't get errors, just a black screen. Turns out core renders black by default. I changed my clear color to something lighter and BAM!... there's the black rectangle.
It's a bit sad that you don't use shaders as they really are what gives you controll over your GPU (kind of). Plus, your code wouldn't run on a GPU with a driver that doesn't specify a default shader ...
These videos not only teach me OpenGL but also teach me a lot about Programming in general. Exicted to finish these videos and follow along other playlists.
OpenGL is a `state machine` model kind of program. For finite state machine, we have only one state at a particular time, but for state machine there maybe more than one state. so, that is why @10:17 we can create VAO before creating the buffer itself.
When i got to this video,.i had to stop and review previous ones. And i watched everything deom VBuffers to here twice. Totally worth it. These explanations are really good.
If you abstract all this away, you're going to stop learning opengl, and instead you will just be learning how to use the abstractions you made. And those abstractions are unlikely to be very good, since your understanding of the underlying subject is currently very limited. If you actually want to learn opengl (so you can later make good abstractions around opengl), delete your source code (including your shaders) and retype it. Repeat until you can do it from memory. Then watch the videos again to make sure you understand the code you've now memorized. Then start changing things around (between using glDrawArrays vs glDrawElements, change the color and number of vertices, etc...) , to make sure you understand what each part is doing. Once you've done all that, make your own abstractions.
so if i understand correctly, the vertex array object takes care of the binding of the vertex buffer and vertices attributes by itself, and in the compatibility profile there is only one VAO for the whole program, which is why we need to rebind everything by hand everytime we issue a draw call
vertex arrays object can store vertex buffer and index buffer(element buffer) too but you didn't mention it in your video, so it will make your life a bit easier
Finally going through this series and that 6 vs 4 thing screwed me up when I was trying to reimplement it with 3 triangles until I realized you made a mistake and it was not some weird thing based on the index buffer.
Protip if you want to get as modern as OpenGL gets, 4.5 introduced glVertexArrayVertexBuffer and glVertexArrayElementBuffer, which explicitly bind a vertex or element buffer to a specific vertex array, rather than just leaving it out in the open like glBindBuffer(GL_ARRAY_BUFFER) and glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) do. Also, I find it's easiest to think about GL vertex arrays as corollary to the D3D11 InputLayout object, since they generally just store metadata that is used to interpret buffers.
It seems like the word Cherno is struggling over here is "Vertex Attribute Array". He calls it by many names "layout", "vertex layout", "buffer layout object", "specification", etc. The VAA is what joins VAOs to VBOs, and defines the type of data contained by VBOs.
I'm a bit confused on what's happening in this video. My understanding at the moment is that starting from the code he provided in previous video if I switched from compatibility to core I would get an error, and that's because I haven't explicitly bounded any Vertex Array object. To sort this out I need to use create a vertex array, and bind it. Is this correct so far? What I don't get at the moment is the advantage. Assuming I'm in compatibility mode, the main advantage seems to be if had to render multiple geometry, with different layouts I can just specify the layout once (with a vertex array bounded) and when I'm calling the draw call I need to bind the right vertex array instead of re-specifying the layout for the different geometries, is this correct? Can you please confirm?
This is correct. In this video, the point of VAOs is a bit hard to understand because we aren't actually drawing from 2 different vertex buffers. But just as you explained, if you have multiple vertex buffers, you dont want to bind them and then their layout explicitly every time you want to draw them. That is not the only advantage of VAOs though. You can bind other stuff to VAOs as well as far as I know, like index buffers, uniforms and shaders and so on. Hope that helps. Maybe check out the OpenGL spec and give the VAO section a read.
16:10 I understand that you bind a vao everytime you want to draw a different object, but I'm not sure once you've bound your vao, can't you directly draw it without binding an ibo? Since I thought the ibo was also linked to the vao, so that only calling the vao suffice. correct me if i'm wrong? Anyway, these tutorials are really the goldmine of youtube, very nice content thanks a lot for these
It specifies the location in the shader yes, but the buffer where the data is supposed to come from has to be bound at the time of calling the function.
Strangely, the glfwWindowHint doesn't seem to change the OpenGL Version on my dedicated NVIDIA GPU. Output still shows it using 4.6.0 on nvidia (latest). However, if I switch it back to my integrated intel GPU, it correctly sets to OpenGL 3.3. What gives?
At (8:10) you have us add three lines of code that supposedly changes the GLFW Version to 3.3 /* Vid#12 (8:10) OpenGL GLFW Version 3.3 create an Open Context and Window with the Core Profile */ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); The result is a window with a black screen. And the console output produces: C:\Dev\Cherno\OpenGL\bin\Win32\Debug\OpenGL.exe (process 6192) exited with code -1. To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops. Press any key to close this window . . . If I comment out these (3) code lines, the console output produces: 2.1.0 - Build 8.15.10.2900 Any ideas Chero? Thank you in advance.
So, my default GLFW Version is 2.1.0 - Build 8.15.10.2900 And, the code above ONLY works as follows: glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE); Note: ONLY (GLFW_CONTEXT_VERSION_MAJOR, 2) and (GLFW_CONTEXT_VERSION_MINOR, 1) WORKS!!! All other combinations of ints (e.g. 2, 3) of LATER major/minor versions Fails with console output msg: For major 3 and minor 3: glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE); The console output reads: C:\Dev\Cherno\OpenGL\bin\Win32\Debug\OpenGL.exe (process 7768) exited with code -1. To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops. Press any key to close this window . . . Earlier major/minor versions (GLFW_CONTEXT_VERSION_MAJOR, 2) and (GLFW_CONTEXT_VERSION_MINOR, 0) Work but default to GLFW Version is 2.1.0 - Build 8.15.10.2900 Why does this FAIL in this way? What is the root cause? What is the solution?
When adding these lines of code, I don't even get output, just a blank screen and an infinite loop that prevents progression from the first glfwWindowHint. Changing the contents of the hints doesn't do anything for me :(
I might be talking shit but looking at your default OpenGL version (2.1) usually being the newest for your device/driver, it seems that 3.3 is not compatible because it's too new (maybe).
If anyone is looking to use OpenGL on a recent Mac, you might need to include this line to avoid segmentation faults: glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
@@I_hate_HANDLESI tried on a Mac as well. I tried a bunch of different things I found online. It seems that Apple does not support openGL anymore. I have a non macos computer as well that I am using to learn openGL, but I eventually plan to learn another API as well because it seems that openGL is beginning to be less and less supported and used in popular applications. Edit: To summarize from my limited knowledge. I would use OpenGL to start learning if you have a non macOS computer and then learn another API for use on specific systems. Or just learn Metal or another one to start out if you like to stick with MacOS. I just started with OpenGL because it works on my machine and it is easier to learn with more tutorials and help online.
When i set these: glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE); it won't change the version in the COMPAT profile just in CORE - its not that important but does someone experience the same or can describe why this happens?
I think it's definitely something that should've been covered earlier in the series. It's fundamental if you're stuck with the core profile by default.
Neither the IBO nor the VBO need a glBufferData() call after being unbound since the data only needs to be initialized once. If you wanted to draw more objects, you would simply generate and bind *new* VBO and IBOs (nothing is overwritten). As he said in the video, the VertexAttrib calls are done because the layout may have changed from drawing objects with a different layout. At this point in the video we were working with a *single* VAO. So unlike the other buffers, that data would need to be overwritten to draw geometry with a different layout than the previous draw call. That's my understanding anyway, I'm a noob myself so don't quote me on that.
I don't know if I am right or not that vertex array object exactly store the current binding for GL_ELEMENT_ARRAY_BUFFER, we just need one invoke for bind index buffer, the index buffer object will store in the current bound VAO object, not only for vertex buffer object.
is there any reason why you specify the size in bytes of an array by manually calculating it through `4 * 2 * sizeof(float)` instead of just using `sizeof(positions)`
I think he did that earlier in the tutorial to illustrate that the value going in there are the number of bytes, not the number of elements or the like
I was facing issue in glGenVertexArrays(1, &vao); where vao is used as vertex array object (u_int vao;) was getting error like.. glGenVertexArrays Access violation executing location 0x00000000 I see that adding glewExperimental = GL_TRUE; resolves that.. any idea why I was getting that and why this is resolving.
I think you should be using VAOs for different _kinds_ of geometry, not one for every geometry. Like all mesh models are probably going to be 3 floats per vertex, while the particles or menus are going to be 2 ints or floats per vertex. I am not actually sure if this is going to be faster tho
+TheChernoProject By playing a little with what we build so far i noticed something weird: If i bind my Index buffer BEFORE binding the VAO, i get a black screen. Do you know why? I mean, VAO is relating VBO's and attribute pointers so why i must bind my index buffer after binding a VAO?
Im pretty much a noob in cpp and opengl and I've only created code using glut... Is there a way to use glut's main loop and all the other glut functions and combine them with glfw just to get rid of immediate mode (all the glBegin() and glEnd()'s that make my cpu usage so high) bevause I dont want to start coding my program from the begining but I want to learn glfw and use its vertexarrays/shader/renderer...
Hi. Why is it necessary to explicitly set the opengl version to 3.2 or greater (using glfwWindowHint) when explicitly setting the profile using glfwWindowHint()? Without the former glfwCreateWindow() fails to create a window.
Are you sure VAO does not store glBindBuffer calls for GL_ELEMENT_ARRAY_BUFFER targets? I never bind index buffer after glBindVertexArray in draw loop and don't encounter any problems. However it is possible that I've been doing it wrong this whole time and drivers were just nice to me...
So if i've understood right binding vao links vertex array with it's layout and that means we can only bind vao instead of every time linking vertex buffer with it's layout. Right?!
Yes, if you bind vertex buffers to the VAO, then you won't need to bind/unbind the specific buffers anymore. You would just be able to use the VAO and the buffer objects will follow.
About performance... Why VAO/VBO performance is 50% worse than immediate mode (glBegin)? I didn't manage to find the answer to this. When I have for example 3600 quads, with glBegin I get 700 fps, and with VAO/VBO 330 fps. And yes, I update vertices every frame, but that's what I actually need in my project. Not just draw big static mesh, but draw a lot of small, not connected quads and move/rotate them every frame. Maybe VAO/VBO is not designed for this task, or maybe I'm doing something wrong, I don't know. For now I'm gonna stick to immediate mode. (if I don't update VAO/VBO every frame I get 2000 fps, btw)
I think that it might be better to abstract all this code to a class first. Because if we add the math library and all that, it will start to become messy.
Yeah, actually OpenGL already has some kind of object concept, basically everything with an ID can be seen as one object: shader programs, vertex buffers, vertex arrays, textures, etc. Instead of glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID) you just would call vertexBuffer.bind() which looks much cleaner.
Damn it, I loved this course up until this video. This one totally jumped the gun. Your couch explanations are not sufficient anymore, you need graphs/pictures. I've heard the word "buffer" so much that it lost all meaning.
I too didn't understood in the first try. I am not sure why, but I now understand 100% of what he is talking about. I know this may sound crazy, but I think you should check out how CPU works, in detail. I think that helped me out...
TheChernoProject - Please, create a mini-program that reads your C program (ex. foo.c), surrounds only the lines starting with "GL" (ex. glUniform4f) with GLCLEARERROR() and GLCHECKERROR(), and writes the result to another C file (ex. fooDEBUG.c) -- This way, you will be able to always show us the original source files, and whenever it's needed to debug the source, using GLCALL(), just run the mini-program instead, and then compile and run the other program that was created by it. -- Your Videos Are Great! I'm following every one of them, and you explain it so clearly with examples. Five Stars!
If it varies between environments why is a test on my environment matter -- it might be totally different for someone else anyway. I think I'd prefer just favoring the simplest way. (Funny, I never thought of looking for a math library before starting to write my own, since that is how Java based tutorials I saw did things.)
+Jared Blackburn your target environment is what I’m talking about. For eg. if you’re targeting Android with predominantly Mali GLES 3 GPUs, test on that
Why would we need one VAO for each object? Why would we need to specify a vertex layout for every object? Presumably we’ve normalized any input geometry to be the same format before we draw it, so wouldn’t it be more efficient to have literally one VAO and one layout for the whole program, because the vertex format won’t change object to object (with some exceptions maybe)?
Anyone who is still confused by vertex array objects/vertex array, vertex attributes/vertex buffers and element buffer objects you just need to look at some flow pipeline in google images and you'll get it
Also important to note that Index Buffer / ELEMENT_ARRAY_BUFFER is also contained within VAO state. It does not need to be redefined per-frame... so you can also remove that line, too.
The GL_ELEMENT_ARRAY_BUFFER has to be bound after the vertex array object has been bound (glBindVertexArray). The GL_ELEMENT_ARRAY_BUFFER object is stored in the vertex array objects state vector.
If the vertex array object has been unbound and is bound again, then the GL_ELEMENT_ARRAY_BUFFER is known and bound again too. But if the element array buffer explicitly gets unbound while the vertex array object is bound, it is removed form the state vector.
Thanks. It seemed weird for vao not to keep track of index buffer as well, like why should it be a separate thing... This makes life easier.
Advanced users set the video Speed to 2, to experience "Churbo" Mode.
lol
xd
That's what I did in the whole series.
I watch RUclips at *2 speed as a default.
Not this video, it's getting so complicated 🙄
15:10 The two options can be stated simply: (A) `COMPAT_PROFILE` means recycling one default/global VAO for everything; this is the default profile for backward-compatibility. (B) `CORE_PROFILE` means defining as many VAOs as you like. Changing VAOs is fewer-calls/optimal/easier/faster than otherwise changing the VAAs + VBOs + IBs many times per frame.
You can actually remove the index buffer binding as well, it is also stored within the VAO
really? that's cool
Cool
mind expanding on that? when I remove glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo) from the while loop and leave it to the VAO I get an error
@@rafaelfernandes4432 Are you binding your index buffer while you still have your vertex array binded? It worked for me, I'm not sure how it would be different for you.
@@staticbits yup, that was it! thank you very much, it didn't occur to me double checking that for some reason. thanks a bunch!
may god bless you. It's incredible how tough it is to find a good explanation, thanks!!!
11:33 you dont need to bind index buffer at all if you bound your vertex array object because vertex array object contain all of it(vertex buffer & index buffer)
I was thinking this as well, but if you switch some lines around - specifically, unbinding the IBO before you unbind the VAO - you'll get a debugbreak at DrawElements();
Anyone knows what's going on beneath the surface here? I say this because if you switch other binds around (for instance, unbinding shader, VBO - or even both - before unbinding the VAO), it will still work, whereas with the IBO it will not.
@@gabrieleboas1129 I've thought about it, and I'm 99% sure that all changes (binding or unbinding) in a vertex buffer, index buffer, or vertex attribute are saved in the bound vertex array. That means that while VAO is bound, IBO being unbound will be saved in the vertex array. I assume this is also why Cherno initialized the vertex array before either the vertex buffer, or index buffer. Once a vertex array is unbound, it's basically inactive.
@@gabrieleboas1129 Im pretty sure that a VAO can only have 1 index buffer and so as soon as he bound it to his VAO, that state was saved and so you don't need to keep rebinding it but if you were to bind GL_ELEMENT_ARRAY_BUFFER to 0 then no buffer would be bound and would probably generate error but im not completely sure
@@elijahvillarmia7742 Vertex Arrays and Index Buffers are 2 entirely different but related pieces of data to OpenGL. A Vertex Array is the actual data used to construct the geometry, whereas an Index Buffer is the instructions on which order it all gets sent to the vertex shader. They are bound separately, and any Index Buffer can be used with any Vertex Array, provided you don't get an out of bounds error with said combination. Another note is that Index Buffers apply to every attribute array in the Vertex Array. So if you've got UV coordinates and normals in there along with vertex positions, a 0 in the Index Buffer means the first vertex position, with the first UV, and the first normal, all get sent to the vertex shader as that "vertex"
I realize this is more of a GL 4.3+ approach, but you could create VAO objects for different purposes (types of models, shaders, etc.) that are re-usable. While setting up the VAO, use the stateless glVertexAttribBinding and glVertexAttribFormat functions that don't bind to a VBO. Then simply bind the appropriate VAO before drawing, bind the VBO using glBindVertexBuffer, bind to the element buffer using glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...), and do your drawing.
Would love to hear more about your day job. Did you have a mentor at EA who taught you a lot of this stuff or are you completely self taught? How do you choose the technology that goes into your games for the high end products? Maybe this is for your vlog, but I think it would be interesting.
yea respond to this cherno
Maldito Cherno responde carajo.
+The Cherno
@The Cherno
@@bryanswaggbeast4594 lol 😂
Thank you very much! Even after reading numerous of opengl pages for VAO, VBO etc.. your videos made them totally clear to me! I mean why is so hard for Khronos to give good explanations!!!! Thanks again!
For anyone who didn't specify a shader at this point: I skipped the shaders part, followed every tutorial except for shaders, so up to now I just got a white rectangle. When using core, I didn't get errors, just a black screen. Turns out core renders black by default. I changed my clear color to something lighter and BAM!... there's the black rectangle.
Thank you, this helped me a lot!
It's a bit sad that you don't use shaders as they really are what gives you controll over your GPU (kind of). Plus, your code wouldn't run on a GPU with a driver that doesn't specify a default shader ...
@@eliaswenner7847 Yes I came to that later. At this point I just wanted to see a triangle.
The default behaviour when there are no shaders is undefined. It depends on the graphics card driver if it will be rendered or what colour
These videos not only teach me OpenGL but also teach me a lot about Programming in general. Exicted to finish these videos and follow along other playlists.
The Cherno is really a great teacher! Learned a lot from him
OpenGL is a `state machine` model kind of program. For finite state machine, we have only one state at a particular time, but for state machine there maybe more than one state.
so, that is why @10:17 we can create VAO before creating the buffer itself.
One more thing Opengl 2.0 does not support `glGenVertexArrays()`
After watching these tutorial 4-5 times and following a course on udemy... I finally get it 😭😭
Congratulations
I still don't 😂😭😭😂
this one is the only thing i dont get....
If you're still confused, check out ThinMatrix's video on VAOs and VBOs.
@@Tresla thank you soo much 😃
Will never get over the majestic bgm in the beginning. Feel like I'm gonna watch a movie.
Wow.. I've binge watched the series and followed along till that point in one go and i am totally hooked
Another great video, Cherno. Big thank you to all the Patreon peeps.
When i got to this video,.i had to stop and review previous ones. And i watched everything deom VBuffers to here twice. Totally worth it. These explanations are really good.
8:11 FUCKING FINALLY!!! I was waiting for that since episode 1!!!
I am starting to get very confused by the code. Some abstraction wouldn't be bad
or is it?... *vsauce theme plays*
Nutter oligist nah, abstraction is a great tool for making your code cleaner and more usable.
clean and usable code is for pussies
If you abstract all this away, you're going to stop learning opengl, and instead you will just be learning how to use the abstractions you made. And those abstractions are unlikely to be very good, since your understanding of the underlying subject is currently very limited. If you actually want to learn opengl (so you can later make good abstractions around opengl), delete your source code (including your shaders) and retype it. Repeat until you can do it from memory. Then watch the videos again to make sure you understand the code you've now memorized. Then start changing things around (between using glDrawArrays vs glDrawElements, change the color and number of vertices, etc...) , to make sure you understand what each part is doing. Once you've done all that, make your own abstractions.
abstraction.. pfft.. our grandfathers were programming potatoes with cards containing holes you spoiled bitches.
so if i understand correctly, the vertex array object takes care of the binding of the vertex buffer and vertices attributes by itself, and in the compatibility profile there is only one VAO for the whole program, which is why we need to rebind everything by hand everytime we issue a draw call
vertex arrays object can store vertex buffer and index buffer(element buffer) too but you didn't mention it in your video, so it will make your life a bit easier
intel drivers dont store the element buffer with the vao
I think you hadn't watched the video he mentioned that in 11:48
@@opressedrage thats not the same thing
Finally going through this series and that 6 vs 4 thing screwed me up when I was trying to reimplement it with 3 triangles until I realized you made a mistake and it was not some weird thing based on the index buffer.
Protip if you want to get as modern as OpenGL gets, 4.5 introduced glVertexArrayVertexBuffer and glVertexArrayElementBuffer, which explicitly bind a vertex or element buffer to a specific vertex array, rather than just leaving it out in the open like glBindBuffer(GL_ARRAY_BUFFER) and glBindBuffer(GL_ELEMENT_ARRAY_BUFFER) do.
Also, I find it's easiest to think about GL vertex arrays as corollary to the D3D11 InputLayout object, since they generally just store metadata that is used to interpret buffers.
Truly amazed of how much youtube automatic subtitles has been improved, the only this that it misses is probably word VAO
11:38 you don't need to bind the index buffer as the vao binds it
It seems like the word Cherno is struggling over here is "Vertex Attribute Array". He calls it by many names "layout", "vertex layout", "buffer layout object", "specification", etc. The VAA is what joins VAOs to VBOs, and defines the type of data contained by VBOs.
I'm a bit confused on what's happening in this video. My understanding at the moment is that starting from the code he provided in previous video if I switched from compatibility to core I would get an error, and that's because I haven't explicitly bounded any Vertex Array object. To sort this out I need to use create a vertex array, and bind it. Is this correct so far? What I don't get at the moment is the advantage. Assuming I'm in compatibility mode, the main advantage seems to be if had to render multiple geometry, with different layouts I can just specify the layout once (with a vertex array bounded) and when I'm calling the draw call I need to bind the right vertex array instead of re-specifying the layout for the different geometries, is this correct? Can you please confirm?
This is correct. In this video, the point of VAOs is a bit hard to understand because we aren't actually drawing from 2 different vertex buffers. But just as you explained, if you have multiple vertex buffers, you dont want to bind them and then their layout explicitly every time you want to draw them. That is not the only advantage of VAOs though. You can bind other stuff to VAOs as well as far as I know, like index buffers, uniforms and shaders and so on. Hope that helps. Maybe check out the OpenGL spec and give the VAO section a read.
@@CMGBgamerz Thanks
16:10 I understand that you bind a vao everytime you want to draw a different object, but I'm not sure once you've bound your vao, can't you directly draw it without binding an ibo? Since I thought the ibo was also linked to the vao, so that only calling the vao suffice. correct me if i'm wrong?
Anyway, these tutorials are really the goldmine of youtube, very nice content thanks a lot for these
I just can't get the vao working, I only have a black screen.
Also if I resize the window then the clear color will set it to blue as it should
At 12:30 you said, that the first parameter is index of a buffer. But I think, it is index of the input attribut in shader, isn't it?
It specifies the location in the shader yes, but the buffer where the data is supposed to come from has to be bound at the time of calling the function.
Yes I know, but he said, that for example number 1 points to a different buffer, which is not true.
It's not the index of the buffer, it's the index of the attribute, which could mean a different buffer but not necessarily.
I see, sorry for misleading.
u mean index of the attribute of the VAO ?
Strangely, the glfwWindowHint doesn't seem to change the OpenGL Version on my dedicated NVIDIA GPU. Output still shows it using 4.6.0 on nvidia (latest). However, if I switch it back to my integrated intel GPU, it correctly sets to OpenGL 3.3. What gives?
why when i add glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE), it make my window be null?
in my opinion, i think that using vao is better that not because it avoid code duplication and it is easier to read
cherno: u might have noticed i typed here but it should be 4
me: * proceeds to render hexagon
At (8:10) you have us add three lines of code that supposedly changes the GLFW Version to 3.3
/* Vid#12 (8:10) OpenGL GLFW Version 3.3 create an Open Context and Window with the Core Profile */
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
The result is a window with a black screen. And the console output produces:
C:\Dev\Cherno\OpenGL\bin\Win32\Debug\OpenGL.exe (process 6192) exited with code -1.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .
If I comment out these (3) code lines, the console output produces:
2.1.0 - Build 8.15.10.2900
Any ideas Chero? Thank you in advance.
So, my default GLFW Version is 2.1.0 - Build 8.15.10.2900
And, the code above ONLY works as follows:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE);
Note: ONLY (GLFW_CONTEXT_VERSION_MAJOR, 2) and (GLFW_CONTEXT_VERSION_MINOR, 1) WORKS!!!
All other combinations of ints (e.g. 2, 3) of LATER major/minor versions Fails
with console output msg:
For major 3 and minor 3:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_ANY_PROFILE, GLFW_OPENGL_CORE_PROFILE);
The console output reads:
C:\Dev\Cherno\OpenGL\bin\Win32\Debug\OpenGL.exe (process 7768) exited with code -1.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .
Earlier major/minor versions (GLFW_CONTEXT_VERSION_MAJOR, 2) and (GLFW_CONTEXT_VERSION_MINOR, 0) Work but default to GLFW Version is 2.1.0 - Build 8.15.10.2900
Why does this FAIL in this way?
What is the root cause?
What is the solution?
When adding these lines of code, I don't even get output, just a blank screen and an infinite loop that prevents progression from the first glfwWindowHint. Changing the contents of the hints doesn't do anything for me :(
I might be talking shit but looking at your default OpenGL version (2.1) usually being the newest for your device/driver, it seems that 3.3 is not compatible because it's too new (maybe).
Finally understood it after re-watching 4 times 😅
If anyone is looking to use OpenGL on a recent Mac, you might need to include this line to avoid segmentation faults:
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
i am using mac but this does not help, i am not sure if it is a segment fault because no "square window" occurred
@@I_hate_HANDLESI tried on a Mac as well. I tried a bunch of different things I found online. It seems that Apple does not support openGL anymore. I have a non macos computer as well that I am using to learn openGL, but I eventually plan to learn another API as well because it seems that openGL is beginning to be less and less supported and used in popular applications.
Edit: To summarize from my limited knowledge. I would use OpenGL to start learning if you have a non macOS computer and then learn another API for use on specific systems. Or just learn Metal or another one to start out if you like to stick with MacOS. I just started with OpenGL because it works on my machine and it is easier to learn with more tutorials and help online.
I'm using the GCC compiler and my code wouldn't work until I added a Vertex Array Buffer, now I know why.
When i set these:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
it won't change the version in the COMPAT profile just in CORE - its not that important but does someone experience the same or can describe why this happens?
Same ...
i have the same problem and setting version to core instead makes the version 3.3.0 for some reason
I enjoyed this video, thanks!
Hey can you do the performance test for this, Global VAO vs different VAO for different VBOs.
Everyone that uses a Mac had to do this in the 2nd episode lol.
I legit updated my os instead. :(
Totally agree, I had to do a lot of research to implement opengl 2.1, and gsl 120 until now that I could finally set it to use OpenGL 3.3
I think it's definitely something that should've been covered earlier in the series. It's fundamental if you're stuck with the core profile by default.
Why is it not necessary to declare glBufferData() for ibo just like we are doing for buffer after unbinding both? @5:33
Neither the IBO nor the VBO need a glBufferData() call after being unbound since the data only needs to be initialized once. If you wanted to draw more objects, you would simply generate and bind *new* VBO and IBOs (nothing is overwritten).
As he said in the video, the VertexAttrib calls are done because the layout may have changed from drawing objects with a different layout. At this point in the video we were working with a *single* VAO. So unlike the other buffers, that data would need to be overwritten to draw geometry with a different layout than the previous draw call.
That's my understanding anyway, I'm a noob myself so don't quote me on that.
@@WilliamAncich thank you!
@@NavyaVedachala No problem, I think forcing myself to think it through helped my own understanding as well.
Thanks cherno
if you are getting a black screen you need to make the vao before the buffer
When I use compatibility mode, the version change seems to be ignored on my pc. It keeps using the newest version.
@Eric got the same thing when I tried to change the version after the window was created, but if I did it before it was fine.
So which one is faster now? Using single VAO or multiple VAOs?
I don't know if I am right or not that vertex array object exactly store the current binding for GL_ELEMENT_ARRAY_BUFFER, we just need one invoke for bind index buffer, the index buffer object will store in the current bound VAO object, not only for vertex buffer object.
Abstraction??? ...Yes, please!
is there any reason why you specify the size in bytes of an array by manually calculating it through `4 * 2 * sizeof(float)` instead of just using `sizeof(positions)`
I think he did that earlier in the tutorial to illustrate that the value going in there are the number of bytes, not the number of elements or the like
@TheCherno Should post an update on VAO benchmark at the end of video, and/or link in description if you've already done so elsewhere.
I was facing issue in glGenVertexArrays(1, &vao); where vao is used as vertex array object (u_int vao;)
was getting error like.. glGenVertexArrays Access violation executing location 0x00000000
I see that adding glewExperimental = GL_TRUE; resolves that.. any idea why I was getting that and why this is resolving.
had the same problem and it works now, bro...
I love you, you saved my ass. Thank you
I think you should be using VAOs for different _kinds_ of geometry, not one for every geometry. Like all mesh models are probably going to be 3 floats per vertex, while the particles or menus are going to be 2 ints or floats per vertex.
I am not actually sure if this is going to be faster tho
Buffffeerrrrrrrrrrrrrrrr!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
closing the generated window causes a breakpoint at glfwTerminate() for me :/ didn't do that before
+TheChernoProject By playing a little with what we build so far i noticed something weird: If i bind my Index buffer BEFORE binding the VAO, i get a black screen. Do you know why? I mean, VAO is relating VBO's and attribute pointers so why i must bind my index buffer after binding a VAO?
Maybe creating a global VAO for static objects and creating seperate VAO's for dynamic objects will be a better approach in terms of GPU memory usage.
what if I want to change that on runtime to draw line ?
Im pretty much a noob in cpp and opengl and I've only created code using glut... Is there a way to use glut's main loop and all the other glut functions and combine them with glfw just to get rid of immediate mode (all the glBegin() and glEnd()'s that make my cpu usage so high) bevause I dont want to start coding my program from the begining but I want to learn glfw and use its vertexarrays/shader/renderer...
Hi. Why is it necessary to explicitly set the opengl version to 3.2 or greater (using glfwWindowHint) when explicitly setting the profile using glfwWindowHint()? Without the former glfwCreateWindow() fails to create a window.
Are you sure VAO does not store glBindBuffer calls for GL_ELEMENT_ARRAY_BUFFER targets? I never bind index buffer after glBindVertexArray in draw loop and don't encounter any problems. However it is possible that I've been doing it wrong this whole time and drivers were just nice to me...
The spec says glBindBuffer for element buffer modifies VAO state in the line below the one he highlights in the video, so I guess it does store it!
That's what I was wondering too. Whenever I do it, the VAO remembers the Index Buffer for me. What version of OpenGL are you using? Im using 4.0
Yeah, just tried it in OpenGL 3.3, it memorizes the index buffer state.
Nvidia presentation link doesn't work anymore (
So if i've understood right binding vao links vertex array with it's layout and that means we can only bind vao instead of every time linking vertex buffer with it's layout. Right?!
Yes, if you bind vertex buffers to the VAO, then you won't need to bind/unbind the specific buffers anymore. You would just be able to use the VAO and the buffer objects will follow.
Link is broken. Has anyone an alternartive?
Crazy stuff. One of my favorite channels (there are only three in total).
Funny enough I unbound the array buffers before calling and it still worked! How is that possible?
If you called glBindBuffer(GL_ARRAY_BUFFER, 0) and still called glDrawElements with a bound Vertex Array Object, that is the expected behavior
FWIW, I'm getting a 1282: on glUseProgram: GL_INVALID_OPERATION is generated if program is not a program object.
to be sure: glUseProgram(shader)
About performance... Why VAO/VBO performance is 50% worse than immediate mode (glBegin)?
I didn't manage to find the answer to this.
When I have for example 3600 quads, with glBegin I get 700 fps, and with VAO/VBO 330 fps.
And yes, I update vertices every frame, but that's what I actually need in my project. Not just draw big static mesh, but draw a lot of small, not connected quads and move/rotate them every frame.
Maybe VAO/VBO is not designed for this task, or maybe I'm doing something wrong, I don't know.
For now I'm gonna stick to immediate mode.
(if I don't update VAO/VBO every frame I get 2000 fps, btw)
It can be late to answer, but maybe you can try to change the value of the last parameter named usage of glBufferData() function.
Siempre creo entenderlo todo hasta que tu lo explicas xD xD.
could I go through the tutorial using glad instead of glew? (are there different functions)
Yes, GLAD is fine
Nice, but just a question are there any benefits of using glew over glad?
@@oj0024 there are 5 years of silence, thats for sure
Where is the link you was talking ABOUT
Just linked it in the description :)
Mia Smith Give me the link
Is it possible to use typedef for those really long functions?
You could use macros, but I wouldn't.
why? is it because you want to just write c++ or would there be some kind of conflict with GL?
I think that it might be better to abstract all this code to a class first. Because if we add the math library and all that, it will start to become messy.
Or you could go procedural and make functions instead ;)
opengl is just a bunch of functions in pure C. If you want to program opengl in an OOP way, try OpenSceneGraph.
u can program openGL in OOP way just by using your brain...MINECRAFT is made in LWJGL(OPenGL) so that is possible
Yeah, actually OpenGL already has some kind of object concept, basically everything with an ID can be seen as one object: shader programs, vertex buffers, vertex arrays, textures, etc. Instead of glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID) you just would call vertexBuffer.bind() which looks much cleaner.
This is not tutorial on game engines, this is a tutorial on opengl
Stupid question ahead: Is this how you get a vertex point on the screen?
no, the vertexbuffer holds the vertexdata, the vertexarray only links the vertexbuffer with it's layout
Is anyone getting just whitescreen with no errors at all?
This happens to me when i accidentally press mouse in a console window, meaning stoping the process. Try pressing enter in console window.
This is too hard for meeeeeeeeeee
Damn it, I loved this course up until this video. This one totally jumped the gun. Your couch explanations are not sufficient anymore, you need graphs/pictures. I've heard the word "buffer" so much that it lost all meaning.
its been 8 months since you posted this up. How has your progress been with OpenGL? :)
@@kevindudeja291 Gave up. When he decided to make his engine 2d instead of 3d I bailed.
I too didn't understood in the first try. I am not sure why, but I now understand 100% of what he is talking about. I know this may sound crazy, but I think you should check out how CPU works, in detail. I think that helped me out...
Would having seperate VAOs lead to better chunking off into classes?
TheChernoProject - Please, create a mini-program that reads your C program (ex. foo.c), surrounds only the lines starting with "GL" (ex. glUniform4f) with GLCLEARERROR() and GLCHECKERROR(), and writes the result to another C file (ex. fooDEBUG.c) -- This way, you will be able to always show us the original source files, and whenever it's needed to debug the source, using GLCALL(), just run the mini-program instead, and then compile and run the other program that was created by it. -- Your Videos Are Great! I'm following every one of them, and you explain it so clearly with examples. Five Stars!
If it varies between environments why is a test on my environment matter -- it might be totally different for someone else anyway. I think I'd prefer just favoring the simplest way.
(Funny, I never thought of looking for a math library before starting to write my own, since that is how Java based tutorials I saw did things.)
+Jared Blackburn your target environment is what I’m talking about. For eg. if you’re targeting Android with predominantly Mali GLES 3 GPUs, test on that
chernos binding adventures
I think, and I said THINK that if you use one VAO for each object, it will be faster if you have a lot of memory. Only if you have a lot of memory.
3:56
I'm getting very confused on what's really going on in the code. Could someone suggest me a book about modern OpenGL for beginners?
3:00 Wow, OpenGL's API design is a real brainfuck :D
Do you have a video, testing the performance you talked about? If not, can you make one?
Why would we need one VAO for each object? Why would we need to specify a vertex layout for every object? Presumably we’ve normalized any input geometry to be the same format before we draw it, so wouldn’t it be more efficient to have literally one VAO and one layout for the whole program, because the vertex format won’t change object to object (with some exceptions maybe)?
I encountered an error. It doesn't show up anymore but it would say Ox0000124. Any idea what that means?
Do you mean vector/matrix mathematics or traditional?
you should make a course on stackskills
nVidia: "Don't use VAOs"
OGL and Cherno "Use them"
Hmm.
Whatever I have amd anyway
Anyone who is still confused by vertex array objects/vertex array, vertex attributes/vertex buffers and element buffer objects you just need to look at some flow pipeline in google images and you'll get it
Just a quick question, are you ever going to finish the 3D java programming tutorials? Please make more.
Hey the Cherno I am wondering if you can make a series on 3D game dev in c# or c++
cool stuff like it!!
Cherno says he doesnt care about performance??
Sadly that modern OpenGl is a huge abstraction , gone far away from real GPU
what
Can you make a OpenGL tutorial in java and try to make game similar to minecraft, that would be awesome. Awesome tutorial btw : D
chernos binding adventures