0

In my OpenGL program I have two shaders. One renders with textures, and the other renders just solid colors. After compiling and linking a shader, I enable a texture coordinate vertex attribute array depending on weather or not the shader contains the attribute.

//This code is called after the shaders are compiled.

//Get the handles
textureU = glGetUniformLocation(program,"texture");
tintU = glGetUniformLocation(program,"tint");
viewMatrixU = glGetUniformLocation(program,"viewMatrix");
transformMatrixU = glGetUniformLocation(program,"transformMatrix");
positionA = glGetAttribLocation(program,"position");
texcoordA = glGetAttribLocation(program,"texcoord");

//Detect if this shader can handle textures
if(texcoordA < 0 || textureU < 0) hasTexture = false;
else hasTexture = true;

//Enable Attributes
glEnableVertexAttribArray(positionA);
if(hasTexture) glEnableVertexAttribArray(texcoordA);

If I am rendering an item that is textured, each element in verts consists of 5 values (x,y,z,tx,ty), but if the item isn't textures, each element in verts contains only 3 values (x,y,z).

Here is the problem: When the first item rendered in the GL context does not have a texture, glDrawElements segfaults! However, if the first item rendered does have a texture, it works fine, and any untextured items after the textured one work fine (that is, until a new context is created).

This chunk of code renders an item

glBindBuffer(GL_ARRAY_BUFFER,engine->vertBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(GLfloat)*item->verts.size(),&item->verts[0],GL_DYNAMIC_DRAW);

item->shader->SetShader();

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,engine->elementBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLuint) * item->indicies.size(),&item->indicies[0],GL_DYNAMIC_DRAW);

if(item->usingTexture)
    item->shader->SetTexture(item->texture->handle);

glUniformMatrix4fv(item->shader->transformMatrixU,1,GL_TRUE,&item->matrix.contents[0]);
glUniformMatrix4fv(item->shader->viewMatrixU,1,GL_TRUE,&item->batch->matrix.contents[0]);
glUniform4f(item->shader->tintU,item->color.x,item->color.y,item->color.z,item->color.w);

glDrawElements(GL_TRIANGLES,item->indicies.size(),GL_UNSIGNED_INT,0); //segfault

Here is the function seen above that sets the shader.

glUseProgram(program); currentShader = program;
GLsizei stride = 12;
if(hasTexture) stride = 20;
glVertexAttribPointer(positionA,3,GL_FLOAT,GL_FALSE,stride,0);
if(hasTexture)
    glVertexAttribPointer(texcoordA,2,GL_FLOAT,GL_FALSE,stride,(void*)12);

As far as I know, this problem is not apparent on Intel Integrated Graphics, which seem to be quite lenient.

Edit: If it is useful to know, I am using GLFW and GLEW.

sFuller
  • 1,145
  • 2
  • 12
  • 23

2 Answers2

2

Try adding corresponding glDisableVertexAttribArray()s after your draw call:

glEnableVertexAttribArray(positionA);
if(hasTexture) glEnableVertexAttribArray(texcoordA);
// draw
glDisableVertexAttribArray(positionA);
if(hasTexture) glDisableVertexAttribArray(texcoordA);
genpfault
  • 47,669
  • 9
  • 68
  • 119
0

The problem is that I enabled the vertex attribute arrays after compiling my shader. This is not where I should have been enabling them.

I enabled the texcoord attribute when compiling the shader, but since the first item didn't use it, glDrawElements would segfault.

I fixed this by enabling the attribute when setting the shader.

sFuller
  • 1,145
  • 2
  • 12
  • 23