In a C++ application I am writing I am trying to draw a quad using an EBO (element buffer object). Whenever I try to I can't get that quad to draw at all. What am I doing wrong?
code:
//vertices and indices
GLfloat vertices[]={
//position texture coordinate
-0.005f,0.02f,0.0f, 0.0f,1.0f,
0.02f,0.02f,0.0f, 1.0f,1.0f,
0.02f,-0.02f,0.0f, 1.0f,0.0f,
-0.005f,-0.02f,0.0f, 0.0f,0.0f,
};
GLfloat indices[]={
0,1,3,
2,3,1
};
//initialization
glCreateVertexArrays(1,&VAO);
glBindVertexArray(VAO);
glCreateBuffers(1,&VBO);
glCreateBuffers(1,&EBO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5*sizeof(GLfloat),(GLvoid*)nullptr);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5*sizeof(GLfloat),(GLvoid*)(3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
//drawing commands
transformLocation=glGetUniformLocation(textureProgram,"transform");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,woodTexture);
glUseProgram(textureProgram);
glUniformMatrix4fv(transformLocation,1,GL_FALSE,glm::value_ptr(transform));
glBindVertexArray(bowHandleVAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,bowHandleEBO);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,nullptr);
This works with the glDrawArrays equivalent to this, but whenever I try to Use EBOs it won't draw anything. Comment if you need more information.
The most immediate error that I can see is a type mismatch between your indices definitions and usage at calling glDrawElements
Suggestion: Change GLFloat to GLuint, i.e., define your indices as:
GLuint indices[]={ //...
In addition to what Amadeus says about changing your indices array from float to GLuint, you seem to be using the wrong VAO and EBO. In the code you show us you buffer all your data into a buffer object in VAO and indices to EBO, but then when you try to draw you're drawing with bowHandleVAO and bowHandleEBO.
Related
From what I understand VAOs should store the states needed for rendering like the buffers and the attribute pointers.
But the problem I am having is, I need to set-up the VAO and load the data to the buffers every time before rendering or else the things being drawn is wrong.
I am using a class called mesh that hold the VAO and VBO handles as protected GLuint variables to initialize and load the vertex data into the GPU.
I searched for hours but it seams no one else is having the same problem.
So if I initialize like this and render like this :
mesh coneMesh, sphereMesh, boxMesh;
coneMesh.setup(coneVertex, GL_STATIC_DRAW, 1, ShaderA);
sphereMesh.setup(*sphereVertex, GL_STATIC_DRAW,1, ShaderA);
boxMesh.setup(boxVertex, GL_STATIC_DRAW, 1, ShaderA);
and in the rendering loop:
//sphereMesh.setup(*sphereVertex, GL_STATIC_DRAW,1, ShaderA);
sphereMesh.render(GL_TRIANGLE_STRIP,0,sphereVertex->size(),0);
sphereMesh.render(GL_TRIANGLE_STRIP,0,sphereVertex->size(),1);
//coneMesh.setup(coneVertex, GL_STATIC_DRAW, 1, ShaderA);
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
coneMesh.render(GL_TRIANGLE_STRIP,0,coneVertex.size(),2);
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
//boxMesh.setup(boxVertex, GL_STATIC_DRAW, 1, ShaderA);
boxMesh.render(GL_LINE_LOOP, 0, boxVertex.size());
glfwSwapBuffers(window);
If I take out he comments and reinitialize the VAO and reload the data every thing works perfectly, can someone please tell me what I am doing wrong and how to fix it? Thank You
int mesh::setup(std::vector<vertex> &vert, GLenum BufferDataUsage, GLuint nuberOfAttribute, shader &shad)
{
this->nuberOfAttribute = nuberOfAttribute;
this->shad = &shad;
std::vector<glm::vec3> position;
std::vector<glm::vec2> textureCoord;
position.reserve(vert.size());
textureCoord.reserve(vert.size());
for(unsigned int i; i<vert.size(); i++)
{
position.push_back(vert[i].pos());
textureCoord.push_back((vert[i].textureCoordinate));
}
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1,&vbo[0]);
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);
glBufferData(GL_ARRAY_BUFFER,(GLsizeiptr)vert.size() * sizeof (position[0]), &position[0], BufferDataUsage);
glEnableVertexAttribArray(0);
glVertexAttribPointer ( ( GLuint ) 0, 3, GL_FLOAT, GL_FALSE,0,0);
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
std::cout <<vbo[0]<<std::endl;
return 0;
}
And the rendering function:
void mesh::render(GLenum DrawHint, GLint first,GLsizei count)
{
shad->bind();//glUseProgram(id)
//set up transform matrix and set up uniform
glBindVertexArray(vao);
glDrawArrays(DrawHint, first, count);
glBindVertexArray(0);
Edit
1.)I have ran the code in another machine and the problem didn't go away. So it's probably not a driver bug.
2.)I can confirm that the different VAO and VBO are not overwriting each other since the handles on each of them is unique.
3.) Now I have no idea what could possibly course this problem.
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
Unbinding the VBO has to go after unbinding the VAO, as otherwise VAO will remember your VBO not being bound.
EDIT
As pointed out in comments, it's OK to unbind GL_ARRAY_BUFFER before unbinding the VAO. It wouldn't be OK for GL_ELEMENT_ARRAY_BUFFER, which is not used in this example though.
Therefore, the problem must lie elsewhere.
I take multiple images of the same mesh using OpenGL, GLEW and GLFW. The mesh (triangles) doesn't change in each shot, only the ModelViewMatrix does.
Here's the important code of my mainloop:
for (int i = 0; i < number_of_images; i++) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* set GL_MODELVIEW matrix depending on i */
glBegin(GL_TRIANGLES);
for (Triangle &t : mesh) {
for (Point &p : t) {
glVertex3f(p.x, p.y, p.z);
}
}
glReadPixels(/*...*/) // get picture and store it somewhere
glfwSwapBuffers();
}
As you can see, I set/transfer the triangle vertices for each shot I want to take. Is there a solution in which I only need to transfer them once? My mesh is quite large, so this transfer takes quite some time.
In the year 2016 you must not use glBegin/glEnd. No way. Use Vertex Array Obejcts instead; and use custom vertex and/or geometry shaders to reposition and modify your vertex data. Using these techniques, you will upload your data to the GPU once, and then you'll be able to draw the same mesh with various transformations.
Here is an outline of how your code may look like:
// 1. Initialization.
// Object handles:
GLuint vao;
GLuint verticesVbo;
// Generate and bind vertex array object.
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Generate a buffer object.
glGenBuffers(1, &verticesVbo);
// Enable vertex attribute number 0, which
// corresponds to vertex coordinates in older OpenGL versions.
const GLuint ATTRIBINDEX_VERTEX = 0;
glEnableVertexAttribArray(ATTRIBINDEX_VERTEX);
// Bind buffer object.
glBindBuffer(GL_ARRAY_BUFFER, verticesVbo);
// Mesh geometry. In your actual code you probably will generate
// or load these data instead of hard-coding.
// This is an example of a single triangle.
GLfloat vertices[] = {
0.0f, 0.0f, -9.0f,
0.0f, 0.1f, -9.0f,
1.0f, 1.0f, -9.0f
};
// Determine vertex data format.
glVertexAttribPointer(ATTRIBINDEX_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
// Pass actual data to the GPU.
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*3, vertices, GL_STATIC_DRAW);
// Initialization complete - unbinding objects.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// 2. Draw calls.
while(/* draw calls are needed */) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
// Set transformation matrix and/or other
// transformation parameters here using glUniform* calls.
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0); // Unbinding just as an example in case if some other code will bind something else later.
}
And a vertex shader may look like this:
layout(location=0) in vec3 vertex_pos;
uniform mat4 viewProjectionMatrix; // Assuming you set this before glDrawArrays.
void main(void) {
gl_Position = viewProjectionMatrix * vec4(vertex_pos, 1.0f);
}
Also take a look at this page for a good modern accelerated graphics book.
#BDL already commented that you should abandon the immediate mode drawing calls (glBegin … glEnd) and switch to Vertex Array drawing (glDrawElements, glDrawArrays) that fetch their data from Vertex Buffer Objects (VBOs). #Sergey mentioned Vertex Array Objects in his answer, but those are actually state containers for VBOs.
A very important thing you have to understand – and the way you asked your question it's apparently something you're not aware of, yet – is, that OpenGL does not deal with "meshes", "scenes" or the like. OpenGL is just a drawing API. It draws points… lines… and triangles… one at a time… with no connection between them whatsoever. That's it. So when you show multiple views of the "same" thing, you must draw it several times. There's no way around this.
Most recent versions of OpenGL support multiple viewport rendering, but it still takes a geometry shader to multiply the geometry into several pieces to be drawn.
I'm trying to implement a batch-rendering system using OpenGL, but the triangle I'm trying to render doesn't show up.
In the constructor of my Renderer-class, I'm initializing the VBO and VAO and also load my shader program (this does work, so the error can't be found here). The VBO is supposed to be capable of holding the maximum amount of vertices I'll permit which is defined in the header to be 30000. The VAO contains the information about how the data that I'll store in that buffer is laid out - in this case I use a struct called VertexData which only contains a 3D-vector ('vertex'), but will also contain stuff like colors etc. later on. So I create the buffer with the size I already stated, don't fill in any content yet and provide the layout using 'glVertexAttribPointer'. The '_vertexCount', as the name implies, counts the amount of vertices currently stored inside that buffer for drawing purposes.
The constructor of my Renderer-class (note that every private member variable defined in the header file starts with an _ ):
Renderer::Renderer(std::string vertexShaderPath, std::string fragmentShaderPath) {
_shaderProgram = ShaderLoader::createProgram(vertexShaderPath, fragmentShaderPath);
glGenBuffers(1, &_vbo);
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, RENDERER_MAX_VERTICES * sizeof(VertexData), NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) 0);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
_vertexCount = 0;
}
Once the initization is done, to render anything, the 'begin' procedure has to be called during the main-loop. This gets the current buffer with write permissions to fill in the vertices that should be rendered in the current frame:
void Renderer::begin() {
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
_buffer = (VertexData*) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
}
After beginning, the 'submit' procedure can be called to add vertices and their corrosponding data to the buffer. I add the data to the location in memory the buffer currently points to, then advance the buffer and increase the vertexcount:
void Renderer::submit(VertexData* data) {
_buffer = data;
_buffer++;
_vertexCount++;
}
Finally, once all vertices are pushed to the buffer, the 'end' procedure will unmap the buffer to enable the actual rendering of the vertices, bind the VAO, use the shader program, render the provided vertices as triangles, unbind the VAO and reset the vertex count:
void Renderer::end() {
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(_vao);
glUseProgram(_shaderProgram);
glDrawArrays(GL_TRIANGLES, 0, _vertexCount);
glBindVertexArray(0);
_vertexCount = 0;
}
In the main loop I'm beginning the rendering, submitting three vertices to render a simple triangle and ending the rendering process. This is the most important part of that file:
Renderer renderer("../sdr/basicVertex.glsl", "../sdr/basicFragment.glsl");
Renderer::VertexData one;
one.vertex = glm::vec3(-1.0f, 1.0f, 0.0f);
Renderer::VertexData two;
two.vertex = glm::vec3( 1.0f, 1.0f, 0.0f);
Renderer::VertexData three;
three.vertex = glm::vec3( 0.0f,-1.0f, 0.0f);
...
while (running) {
...
renderer.begin();
renderer.submit(&one);
renderer.submit(&two);
renderer.submit(&three);
renderer.end();
SDL_GL_SwapWindow(mainWindow);
}
This may not be the most efficient way of doing this and I'm open for criticism, but my biggest problem is that nothing appears at all. The problem has to lie within those code snippets, but I can't find it - I'm a newbie when it comes to OpenGL, so help is greatly appreciated. If full source code is required, I'll post it using pastebin, but I'm about 99% sure that I did something wrong in those code snippets.
Thank you very much!
You have the vertex attribute disabled when you make the draw call. This part of the setup code looks fine:
glBindVertexArray(_vao);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glEnableVertexAttribArray(0);
glBufferData(GL_ARRAY_BUFFER, RENDERER_MAX_VERTICES * sizeof(VertexData), NULL, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const GLvoid*) 0);
At this point, the attribute is set up and enabled. But this is followed by:
glDisableVertexAttribArray(0);
Now the attribute is disabled, and there's nothing else in the posted code that enables it again. So when you make the draw call, you don't have a vertex attribute that is actually enabled.
You can simply remove the glDisableVertexAttribArray() call to fix this.
Another problem in your code is the submit() method:
void Renderer::submit(VertexData* data) {
_buffer = data;
_buffer++;
_vertexCount++;
}
Both _buffer and data are pointers to a VertexData structure. So the assignment:
_buffer = data;
is a pointer assignment. Instead of copying the data into the buffer, it modifies the buffer pointer. This should be:
*_buffer = *data;
This will copy the vertex data into the buffer, and leave the buffer pointer unchanged until you explicitly increment it in the next statement.
I have an OpenGL 1.1 ES 2D sprite engine that's based on one GL_TRIANGLE_FAN per sprite. The main rendering code that gets called per-sprite, per-frame is as follows:
void drawTexture(BitmapImage* aImage, short* vertices, float* texCoords,
ColorMap &colorMap, TInt xDest, TInt yDest, TInt aAlpha)
{
glPushMatrix();
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, textureId);
glVertexPointer(3, GL_SHORT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glColorPointer(RGBA_BYTES, GL_UNSIGNED_BYTE, 0, colorMap.GetMap());
TFloat scaleX, scaleY;
aImage->getScale(scaleX, scaleY);
glTranslatef((float)xDest, (float)yDest, 0.0f);
glScalef(scaleX, scaleY, 1.0f);
glRotatef(aImage->getRotAngle(), 0.0f, 0.0f, 1.0f);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glPopMatrix();
}
I've been told that switching to Vertex Buffer Objects (VBOs) will significantly increase the performance of rendering, so I'd like to do that. My research thus far has lead me to several examples showing how to set up individual vertex, color, and texture offset buffers, but good examples of how to interleave this data have been more elusive.
For example, I'm pretty sure this is how I'd set up to render with my vertex data in a VBO:
glGenBuffers(1, &batchBufferHandle);
glBindBuffer(GL_ARRAY_BUFFER, batchBufferHandle);
glBufferData(GL_ARRAY_BUFFER, dataSize, data, GL_STATIC_DRAW);
glVertextPointer(3, GL_SHORT, 0, 0);
glDrawElements(..., 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDeleteBuffers(1, &batchBufferHandle);
Apparently I'd generate and bind similar buffers for texture coordinates and vertex color data, though I'm not 100% clear on how setting those up would differ.
My understanding is that the speed boost would come from rendering a bunch of these triangle fans in one "draw call", but what is a "draw call" in this context? DrawElements() gets called multiple times using this methodology, so that can't be it...?
Whatever the case, it would mean that I'd have to generate a VBO (or three) that contain all the data in series for a bunch of sprites. That can be difficult enough on its own given the legacy code I'm dealing with, but I also need to translate, scale, and rotate each individual sprite. Where does that data go in the VBO(s)?
My conclusion thus far is using VBOs is only helpful in the case of a SINGLE, but complex object. It would appear what I want to do is not possible -- provide OpenGL with a list of sprites to render (including all vertex, color, texture map, scale, rotation, and translation information for each).
Is my assessment correct or is there a way to do this (using OpenGL ES 1.1)?
I am trying to convert the following piece of code into one that uses a vertex buffer:
glBegin (GL_QUADS);
glTexCoord2fv (&_vertex[ci->index_list[7]].uv.x);
glVertex3fv (&_vertex[ci->index_list[7]].position.x);
glVertex3fv (&_vertex[ci->index_list[5]].position.x);
glVertex3fv (&_vertex[ci->index_list[3]].position.x);
glVertex3fv (&_vertex[ci->index_list[1]].position.x);
glEnd ();
My faulty code partly looks like this:
GLfloat * p = (GLfloat *) malloc(sizeof(GLfloat)*14);
//Memcopies vertices into p pointer
memcpy(&p[counter+0], &_vertex[ci->index_list[7]].uv.x, sizeof(GLfloat)*2);
memcpy(&p[counter+2], &_vertex[ci->index_list[7]].position.x, sizeof(GLfloat)*3);
memcpy(&p[counter+5], &_vertex[ci->index_list[5]].position.x, sizeof(GLfloat)*3);
memcpy(&p[counter+8], &_vertex[ci->index_list[3]].position.x, sizeof(GLfloat)*3);
memcpy(&p[counter+11], &_vertex[ci->index_list[1]].position.x, sizeof(GLfloat)*3);
glGenBuffers(1, &vboId1);
glBindBuffer(GL_ARRAY_BUFFER, vboId1);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*14, p, GL_STATIC_DRAW_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat)*14, (GLfloat*)0);
glVertexPointer(3, GL_FLOAT, 0, 2+(GLfloat*)0);
glDrawArrays(GL_QUADS, 0, 1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
However, I get an "Access violation reading location" error on the glDrawArrays line. Any ideas what could be wrong here? I am very new to OpenGL/graphics and pretty sure I'm messing up something obvious.
This is not going to work. Immediate mode allowed you to omit respecifying unchanged attributes between vertices. But with vertex arrays, you cannot do that. What you currently do is telling the GL that it finds the TexCoords of the i-th vertex at byte offset 14*sizeof(GLfloat)*i in the buffer. For the first vertex, it will work, but for the second, you try to access data beyond the end of the buffer.
You have to duplicate that data, so that every vertex has exactly the same attributes, in the same layout. Basically, you need one vertex array per attribute, with one entry for every vertex, no matter it the value did change or not.
Better view a vertex as not just the position (specified by the glVertex command), but the complete n-tupel of relevant attributes. If any single component of any attribute differs, it is not to be considered the same vertex anymore.