glDrawArrays throws 1282 error and does not draw anything - c++

I checked this question.
gldrawarrays does not draw anything => not applicable because I am using shaders.
My code goes as follows:
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
This initialises a vao first.
GLuint vertexBuffer;
glGenBuffers(1,&vertexBuffer);
float vertices[]={
-0.5f,-0.5f,
0.0f,0.0f,
0.5f,0.5f
};
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
Binds the buffer and adds the data
const char* vertexSource = reader("./shaders/chapter-one.vert").c_str();
GLuint vShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vShader, 1, &vertexSource, NULL);
glCompileShader(vShader);
GLint vStatus;
glGetShaderiv(vShader, GL_COMPILE_STATUS, &vStatus);
if(vStatus!=GL_TRUE){
printf("Vertex Shader not Compiled\n");
}
char vBuffer[512];
glGetShaderInfoLog(vShader, 512, NULL, vBuffer);
cout<<vBuffer;
const char* fragmentSource = reader("./shaders/chapter-one.frag").c_str();
GLuint fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fShader, 1, &fragmentSource, NULL);
glCompileShader(fShader);
GLint fStatus;
glGetShaderiv(fShader, GL_COMPILE_STATUS, &fStatus);
if(fStatus!=GL_TRUE){
printf("Fragment Shader not compiled");
}
char fBuffer[512];
glGetShaderInfoLog(fShader, 512, NULL, fBuffer);
cout << fBuffer;
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vShader);
glAttachShader(shaderProgram, fShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
Adds the shader and creates a program. I also retrieve errors and logs for each step which are empty currently. So no errors compiling or creating shaders and program.
GLuint posLoc = glGetAttribLocation(shaderProgram, "p");
printf("%i\n", posLoc);
glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posLoc);
Gets the attribute from shader to feed the data to.
glDrawArrays(GL_LINES, 0, 3); // => This part does not work
Upon calling glGetError() after glDrawArrays I get 1282 error. I know glDrawArrays is causing this error as just before glDrawArrays I tried calling glGetErrors() and there wer no errors.
I think the problem is in setup somewhere
Any Suggestions??
Edit: I tried changing my code according to Rabbid76's suggestion and I am still getting the same error.
I checked the documentation and I think this is the applicable case.
GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to an enabled array and the buffer object's data store is currently mapped.
What does it mean in this situation and what changes should I make?
Full code here
Yes, I got took both my code and example code side by side and changed anything that seemed inconsistent. I changed both glDrawElements and had to adjust my glVertexAttribPointer. Stupid mistake. Thank you.

There is no glDrawArrays in your code. There is just a glDrawElements and that will cause an error, because you have not specified any Index buffer.
Furthermore, the type argument to glDrawElements has to be the type of the indices. The allowed types are GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT.
Remove glDrawElements and use glDrawArrays to solve the issue:
glDrawElements(GL_TRIANGLES, 3, GL_FLOAT, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
Furthermore the Vertex Buffer Object and the Vertex Array Object have to be bound, before invoking glVertexAttribPointer. glVertexAttribPointer associates the buffer which is currently bound to the target GL_ARRAY_BUFFER to the specified attribute (index) and states the specification in the state vector of the Vertex Array Object.
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);

Related

OpenGL doesn´t render a square

i´m currently running opengl 4.5.
I copy pasted a code from internet to draw a triangle, and it worked just fine. I played with the shaders and everything was great.
Then i had a great idea, why not draw a square, so i tried and it just renders the background.
Here is the code :
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
// Build and compile our shader program
// Vertex shader
vertexShaderSource = read_file("res/shaders/vxShader.vert").c_str();
fragmentShaderSource = read_file("res/shaders/fgShader.frag").c_str();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// Check for compile time errors
GLint success;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// Check for compile time errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// Link shaders
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// Check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// Set up vertex data (and buffer(s)) and attribute pointers
GLfloat vertices[] = {
0.5f, 0.5f, 0.0f, // Left
0.0f, 0.5f, 0.0f, // Right
0.0f, 0.0f, 0.0f, // Top
0.5f, 0.0f, 0.0f // Top
};
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(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(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind
glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs)
// Game loop
while (!glfwWindowShouldClose(window))
{
// Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
glfwPollEvents();
// Render
// Clear the colorbuffer
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_POLYGON, 0, 4);
glBindVertexArray(0);
// Swap the screen buffers
glfwSwapBuffers(window);
}
// Properly de-allocate all resources once they've outlived their purpose
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// Terminate GLFW, clearing any resources allocated by GLFW.
glfwTerminate();
return 0;
Just in case, i only added one vertex to the buffer and i changed glDrawArrays parameter from GL_TRIANGLE to GL_POLYGON. I guess i forgot to do something.
The primitive type GL_POLYGON is deprecated and only supported by a compatibility profile OpenGL context. If you use a core profile OpenGL context then you have to use the OpenGL primitive type GL_TRIANGLE_FAN instead:
glDrawArrays(GL_POLYGON, 0, 4);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
Note, OpenGL can only render points, lines and triangles. If you want to render a polygon shape, then you have to assemble it by triangles. A quad can be formed by 2 triangles. See Primitive.

OpenGL - tell vertex shader that VBO has changed

I am currently writing a program that requires updating my VBO data constantly.
However, I found out that if I call glBindBuffer(GL_ARRAY_BUFFER, 0) after I initialize my buffer, the window closed itself somehow.
Below is my code snippet:
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(pts[0]) * pts.size(), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 3, GL_FLOAT, GL_FALSE,
sizeof(float) * 3, (void*) 0);
while(!glfwWindowShouldClose(window)) {
glUseProgram(program);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pts[0]) * pts.size(), &pts);
glBindBuffer(GL_ARRAY_BUFFER, 0);
mat4x4_mul(mvp, m, p);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glDrawArrays(GL_POINTS, 0, pts.size());
glBindBuffer(GL_ARRAY_BUFFER, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
FYI: pts is constantly updated.
IS there a way to tell vertex shader that the VBO data is updated?
Edit: updated the code snippet
Edit: I am supposed to draw pts.size() number of vertices each time but there is only one point appeared on the screen
Right before your draw call there where you have glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); you need to actually set the attrib pointer(glVertexAttribPointer()). A secondary note is that GlVertexAttribPointer() binds GL_ARRAY_BUFFER to the specified attribute pointer. Where you call it at the moment there is nothing bound to GL_ARRAY_BUFFER.
For reference GLEnum error = glGetError() will return an the error state of openGL and is a powerful debugging tool. If you're using glew, glewGetErrorString() will get a string for any non-zero error code which explains the error in more detail.
p.s. sorry for my poor writing skills.

What does each function for vertex array buffer drawing in OpenGL do?

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.

Can I have multiple GL_ARRAY_BUFFER buffers?

So I was looking at another SO question regarding the command glVertexAttribPointer and I ran into a slight confusion. The accepted answer to this question explains,
But there's an additional implied piece of state that is also stored away for attribute 0 when you make the call: the data is read from the buffer currently bound to GL_ARRAY_BUFFER
This makes sense to me, but what if I have multiple buffers that are bound as GL_ARRAY_BUFFER? How does the glVertexAttribPointer() method know which one to set the attributes of?
For example, in my code, I'm drawing a gradient triangle. To do this, I've created 2 VBOs, one with color data in an array and another with vertex locations.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
static const GLfloat points[] = {
//data here
};
static const GLfloat colors[] = {
//data here
};
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
vs = glCreateShader(GL_VERTEX_SHADER);
fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vs, 1, &vertexShaderData, NULL);
glShaderSource(fs, 1, &fragShaderData, NULL);
glCompileShader(vs);
glCompileShader(fs);
sp=glCreateProgram();
glBindFragDataLocation(sp, 0, "outColor");
glAttachShader(sp, vs);
glAttachShader(sp, fs);
glLinkProgram(sp);
glUseProgram(sp);
glGenBuffers(1, &colorBuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 9);
When I call the command, where do I specify which buffer to use?
This makes sense to me, but what if I have multiple buffers that are bound as GL_ARRAY_BUFFER?
That's not possible. When you bind a buffer (or any OpenGL object) to a target, it automatically unbinds whatever was there before.
OpenGL object targets are like global variables. What happens when you set a global integer to 3? It's old value is gone.
glVertexAttribPointer will always use whatever buffer is currently bound to GL_ARRAY_BUFFER. So in your first call, it will use buffer. In your second call, it will use colorBuffer.
This is why it is important to remember that glVertexAttribPointer operates on what is currently bound. Because even after you bind colorBuffer, and set it to be used by attribute 1, attribute 0 still receives its vertex data from buffer.
So while you cannot have multiple buffers bound to GL_ARRAY_BUFFER, you can use multiple buffers as sources for your vertex data.

Binding a Non-Zero Texture Crashes Program With VBO's

So I wanted to implement a simple VBO to see if it was worth switching from display lists for static objects in my scene. So far, I don't think Im doing it anytime soon. So heres my problem: I can render vertices fine, but as soon as I throw in texture coordinates, it crashes. So I do a bit of experimenting and its because I'm binding a texture to the thing. I have NEVER heard of this as being a problem. Literally the exact same code, using display lists works. Here is my code:
//create a vertex buffer object for the particles to use
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
//create the data, this is really sloppy
float QuadVertextData[] = {0,0,0,1,0,0,1,1,0,0,1,0};
float QuadTextureData[] = {0,1,1,1,1,0,0,0};
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3, &QuadVertextData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//generate another buffer for the texcoords
glGenBuffers(1, &VBOT);
glBindBuffer(GL_ARRAY_BUFFER, VBOT);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2, &QuadTextureData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
and rendering:
glUseProgram(shader);
glBindTexture(GL_TEXTURE_2D, texture);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, VBOT);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
I really have no idea why this is happening, Doing a texture without a shader crashes it, binding a shader without a texture crashes it. Any help or advice?
In a core opengl profile, you need to use VAOs in order to work with calls such as glDrawArrays and glDrawElements. A VAO (vertex array object) is a list of binding points for VBOs that encapsulates information such as data format and number of components for each VBO that is bound to it. In code it looks something like this.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3, &QuadVertextData, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glGenBuffers(1, &vbot);
glBindBuffer(GL_ARRAY_BUFFER, vbot);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2, &QuadTextureData, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glBindVertexArray(0);
The 0 and 1 (the first argument to glVertexAttribPointer) specifies the generic vertex attribute index in your shader. The 2 and 3 (the second argument) specify the number of components. Your input should be defined like this in the shader in order to work with this VAO:
layout(location=0) in vec3 position;
layout(location=1) in vec2 textureCoordinates;
Before drawing anything, you just have to use the shader program, bind your texture and bind the VAO:
glUseProgram(shader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(vao);
glDrawArrays(GL_QUADS, 0, 4);
Don't forget to set the texture location of the sampler2D uniform in the shader.
If you want to learn more about switching to the OpenGL core profile, I recommand the tutorials from http://www.opengl-tutorial.org/