OpenGL VBO Segfault when calling glDrawArrays() - c++

I've been trying to get VBOs working in my latest project and the program segfaults when I try to call glDrawArrays.
Generating the VBO
bool Renderer::init()
{
GLfloat verticies[]=
{0,0,
0,32,
32,32,
32, 0};
glGenBuffersARB(1, &vboTest);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboTest);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verticies), verticies, GL_STATIC_DRAW);
}
And then the rendering the VBO
void Renderer::renderScene()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboTest);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glLoadIdentity();
SDL_GL_SwapWindow(window);
}

Nevermind, it was a stupid arbitrary error. I loaded the functions using SDL_GL_GetProcAddress, but then in the header for the renderer class defined GL_EXT_PROTOTYPES instead of re-prototyping the functions.

Related

OpenGL buffer woes

I've been getting back into OpenGL recently after transitioning to linux. For some reason or another, things like glGenBuffers, glBindBuffer, etc, aren't present with the normal GL headers, and cause my program to crash using GLEW. To get around this I've been using GLES2.
And now the problem:
#include <SFML/Graphics.hpp>
#include <GLES2/gl2.h>
#include <GL/gl.h>
int main() {
sf::RenderWindow window(sf::VideoMode(640, 480), "OpenGL Tests");
glOrtho(0, 640, 0, 480, -1, 1);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glClearColor(0, 0, 0, 0);
//x, y, r, g, b
GLfloat triangleVertices[15] = {
10, 10, 1, 0, 0,
110, 10, 0, 1, 0,
60, 96.6f, 0, 0, 1
};
GLuint triangleBuf;
glGenBuffers(1, &triangleBuf);
glBindBuffer(GL_VERTEX_ARRAY, triangleBuf);
glBufferData(GL_VERTEX_ARRAY, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_VERTEX_ARRAY, 0);
while(window.isOpen()) {
sf::Event event;
while(window.pollEvent(event)) {
if(event.type == sf::Event::Closed) window.close();
}
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_VERTEX_ARRAY, triangleBuf);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 3, 0);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 2, (GLfloat*) 2);
glDrawArrays(GL_TRIANGLES, 0, 3);
window.display();
sf::sleep(sf::milliseconds(50));
}
glDeleteBuffers(1, &triangleBuf);
}
This is how I remember using buffers, though to be honest I don't trust my memory. With good reason it seems, since this crashes immediately after the window opens.
I've tried changing the last argument to glDrawArrays to 1 instead of 3. I've also tried binding the buffer twice, first as GL_VERTEX_ARRAY, followed by glVertexPointer, second as GL_COLOR_ARRAY, followed by glColorPointer. No dice.
The 3rd parameter of glVertexPointer respectively glColorPointer is the byte offset between consecutive (stride). If a named buffer object is bound, then the 4th parameter is treated as a byte offset, too.
The stride parameter has to be 5 * sizeof(GLfloat), because each attribute tuple consists of 5 (GLfloat) components (X, Y, R, G, B). The offset for the vertex coordinates is 0, because they are at the beginning. The offset for the color is 2 * sizeof(GLfloat), because the color comes after the 2 components of the vertex coordinate.
Further more GL_VERTEX_ARRAY is not a valid buffer target. The buffer target for vertex attributes is GL_ARRAY_BUFFER. The wrong usage of GL_VERTEX_ARRAY will cause INVALID_ENUM errors. Error information can be get by glGetError.
Do the following changes:
glGenBuffers(1, &triangleBuf);
glBindBuffer(GL_ARRAY_BUFFER, triangleBuf);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, triangleBuf);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 5*sizeof(GLfloat), 0);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 5*sizeof(GLfloat), (GLfloat*)(2*sizeof(GLfloat)));
Since you do not bind a texture and you do net even have specified texture coordinates, do not enable 2 dimensional texturing:
glEnable(GL_TEXTURE_2D);

Drawing VBO causes segmentation fault

I am trying to draw a quad using a VBO, here is the full code but I'll post the code step by step: here is how I initialize the buffer:
data= vector<GLfloat> { // Global variable vector<GLfloat> data;
// Viewport: glViewport(0,0,width,height);
width/2+20,height/2+20,0.0,
width/2+20,height/2-20,0.0,
width/2-20, height/2-20,0.0,
width/2-20, height/2+20,0.0
};
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 12*sizeof(GLfloat), data.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Then in the display function I try to draw the quad (I use double buffering):
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, data.data());
glDrawArrays(GL_QUADS, 0, 4); // Here I get segmentation fault
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glutSwapBuffers();
I get segmentation fault at the line where I call glDrawArrays, I also tried to get the OpenGL errors with glGetError(), but there's no error (it returns zero).
You are using the following line in the initialization:
glBufferData(GL_ARRAY_BUFFER, 12*sizeof(GLfloat), data.data(), GL_STATIC_DRAW);
When drawing you set up your attrib pointers like this:
glVertexPointer(3, GL_FLOAT, 0, data.data());
I suspect that data.data() is the same in both cases - making this an error. When an ARRAY_BUFFER is bound, the pointer argument of the various gl*Pointer() functions does not refer to a client memory address, but to a byte offset in the VBOs. When drawing, the GL will try to fetch this data which is very likely to be way out of bounds of the buffer object - hence the crash. You probably meant:
glVertexPointer(3, GL_FLOAT, 0, NULL);
Note that the original VBO extension has this often-used macro in the examples section:
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
Using that, you can conveniently hide those ugly pointer arithmetic nicely and can address byte offsets in your buffer:
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));

OpenGL VBO drawing with multitexturing issue

I'm currently using a VBO to draw a series of cubes in OpenGL using a GLSL shader that performs multitexturing (with 5 textures). It works fine if I don't pass the textures in. But if I try to use texturing at all, the whole screen is only drawn white (presumably the last clear color). If I pass the textures in using immediate mode (without the VBO) then it's also fine there. I can't tell why there's a problem.
Code:
// create vertex/normal/color/texcoord VBO
glGenBuffersARB(1, &vboId);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vert_buf)+sizeof(norm_buf)+sizeof(col_buf)+sizeof(tex_buf), 0, GL_STREAM_DRAW);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(vert_buf), vert_buf);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vert_buf), sizeof(norm_buf), norm_buf);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vert_buf)+sizeof(norm_buf), sizeof(col_buf), col_buf);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vert_buf)+sizeof(norm_buf)+sizeof(col_buf), sizeof(tex_buf), tex_buf);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
// create geometry indices VBO
glGenBuffersARB(1, &vboId2);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vboId2);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(index_buf), index_buf, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
// bind vertex/normal/color/texcoord VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
// enable vertex arrays
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
// specify vertex and index arrays with their offsets
glVertexPointer(3, GL_FLOAT, 0, 0);
glNormalPointer(GL_FLOAT, 0, (void*)sizeof(vert_buf));
glColorPointer(3, GL_FLOAT, 0, (void*)(sizeof(vert_buf)+sizeof(norm_buf)));
// bind geometry indices VBO
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vboId2);
glIndexPointer(GL_UNSIGNED_INT, 0, 0);
// set the texture units
GLvoid* start = (void*)(sizeof(vert_buf)+sizeof(norm_buf)+sizeof(col_buf));
glClientActiveTexture(GL_TEXTURE0 + (GLuint)vid_regions[0].tex_id); // same as GL_TEXTURE1
glTexCoordPointer(2, GL_FLOAT, 0, start);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + (GLuint)vid_regions[1].tex_id); // same as GL_TEXTURE2
glTexCoordPointer(2, GL_FLOAT, 0, start);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + (GLuint)vid_regions[2].tex_id); // same as GL_TEXTURE3
glTexCoordPointer(2, GL_FLOAT, 0, start);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + noiseTexID); // same as GL_TEXTURE4
glTexCoordPointer(2, GL_FLOAT, 0, start);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + lutTexID); // same as GL_TEXTURE5
glTexCoordPointer(2, GL_FLOAT, 0, start);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// draw VBOs
glDrawElements(GL_TRIANGLES, 36*ROWS*COLS, GL_UNSIGNED_INT, 0);
// disable arrays
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// disable texture arrays
glClientActiveTexture(GL_TEXTURE0 + (GLuint)vid_regions[0].tex_id);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + (GLuint)vid_regions[1].tex_id);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + (GLuint)vid_regions[2].tex_id);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + noiseTexID);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTexture(GL_TEXTURE0 + lutTexID);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// unbind VBOs
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
Note: the creation of the VBOs is called during the initial setup phase. The drawing happens in a drawing GLUT routine.
Try resetting your texture level back to 0:
glClientActiveTexture(GL_TEXTURE0);
It's not uncommon for weirdness to happen when the active texture level isn't reset (say if you're using FBOs, etc).
It might also be helpful to set your clear colour to something other than black/white/transparent to see if the screen is being drawn with the clear colour or if you're somehow seeing a texel stretched or something else.

Opengles mixing VBO and non VBO renders gives EXC_BAD_ACCESS

Hey guys. Im trying to render two methods shown below. RenderA() is using VBOs and RenderB() isnt. Im getting an EXC_BAD_ACCESS error when it reaches glDrawArrays() in RenderB().
RenderB() works fine though if i dont create and use any VBOs, ie when i comment out CreateVBOs() and RenderA().
So does this mean once you start using VBOs, all renderings must use VBOs?
Or what am I doing wrong here?
Render() {
CreateVBOs(); //glGenBuffers,glBindBuffer,glBufferData etc
RenderA();
RenderB();
}
RenderA(){
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo->indexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vbo->vertexBuffer);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), 0);
glColorPointer(4, GL_FLOAT, sizeof(Vertex), colorOffset);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDrawElements(GL_TRIANGLES,vbo->indexCount, GL_UNSIGNED_SHORT, bodyOffset);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
RenderB(){
static GLfloat vertices[] = {1.0,1.0,1.0,2.0,1.0,1.0};
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawArrays(GL_POINTS, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
}
Edit(Solved)
Figured it out. Apparently you have to make sure you unbind the buffer if it was binded before in order to render without vbo.
My CreateVBOs() function binded but did not unbind the buffer so thats what created bad access when RenderB() was trying to use glDrawArrays. Unbinding the buffer is just binding it to 0 like so:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Try binding GL_ELEMENT_ARRAY_BUFFER and GL_ARRAY_BUFFER to zero before doing your non-VBO draw calls.
Add the following lines of code to the end of your VBO draw calls (RenderA):
glBindBuffer(GL_ElEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);

OpenGL Vertex Buffer Object code giving bad output

My Vertex Buffer Object code is supposed to render textures nicely but instead the textures are being rendered oddly with some triangle shapes.
What happens - http://godofgod.co.uk/my_files/wrong.png
What is supposed to happen - http://godofgod.co.uk/my_files/right.png
This function creates the VBO and sets the vertex and texture coordinate data:
extern "C" GLuint create_box_vbo(GLdouble size[2]){
GLuint vbo;
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLsizeiptr data_size = 8*sizeof(GLdouble);
GLdouble vertices[] = {0,0, 0,size[1], size[0],0, size[0],size[1]};
glBufferData(GL_ARRAY_BUFFER, data_size, vertices, GL_STATIC_DRAW);
data_size = 8*sizeof(GLint);
GLint textcoords[] = {0,0, 0,1, 1,0, 1,1};
glBufferData(GL_ARRAY_BUFFER, data_size, textcoords, GL_STATIC_DRAW);
return vbo;
}
Here is some relavant code from another function which is supposed to draw the textures with the VBO.
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor4d(1,1,1,a/255);
glBindTexture(GL_TEXTURE_2D, texture);
glTranslated(offset[0],offset[1],0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(2, GL_DOUBLE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer (2, GL_INT, 0, 0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDrawArrays(GL_TRIANGLES, 1, 3);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
I would have hoped for the code to use the first three coordinates (top-left,bottom-left,top-right) and the last three (bottom-left,top-right,bottom-right) to draw the triangles with the texture data correctly in the most efficient way. I don't see why triangles should make it more efficient but apparently that's the way to go. It, of-course, fails for some reason.
I am asking what is broken but also am I going about it in the right way generally?
Thank you.
If you want to use the one VBO for both vertex and texture coordinates you need to group them using a struct.
Define your data:
typedef struct {
GLdouble x, y;
GLint s, t;
} VertexData;
VertexData data[] = {
// x y s t
{0.0, 0.0, 0, 0},
{0.0, size[1], 0, 1},
{size[0], 0.0, 1, 0},
{size[0], size[1], 1, 1}
};
Copy it into VBO:
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), (GLvoid*)data, GL_STATIC_DRAW);
Set pointers. Note that stride is your struct's size and pointer itself serves as offset:
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(2, GL_DOUBLE, sizeof(VertexData), (GLvoid*)offsetof(VertexData, x));
glTexCoordPointer(2, GL_INT, sizeof(VertexData), (GLvoid*)offsetof(VertexData, s));
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
And draw.
EDIT: Implemented offset with offsetof() as Bahbar suggested.
You're loading data twice to the vbo. The second call to glBufferData is replacing the first one. Then both calls to gl*Pointer actually use the same data when calling draw.