В моей программе OpenGL у меня есть два шейдера. Один визуализируется с текстурами, а другой — просто сплошными цветами. После компиляции и компоновки шейдера, я включаю массив атрибутов вершин координат текстуры в зависимости от погоды или нет, шейдер содержит атрибут.
//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);
Если я оказываю item
это текстурированный, каждый элемент в verts
состоит из 5 значений (x, y, z, tx, ty), но если элемент не является текстурой, каждый элемент verts
содержит только 3 значения (x, y, z).
Вот проблема: когда первый item
отображается в контексте GL не имеет текстуры, glDrawElements
ошибку сегментации! Однако, если первый визуализированный элемент имеет текстуру, он работает нормально, и любые нетекстурированные элементы после текстурированного работают нормально (то есть до тех пор, пока не будет создан новый контекст).
Этот кусок кода делает 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
Вот функция, показанная выше, которая устанавливает шейдер.
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);
Насколько я знаю, эта проблема не проявляется в Intel Integrated Graphics, которая выглядит довольно снисходительно.
Редактировать: Если это полезно знать, я использую GLFW и GLEW.
Попробуйте добавить соответствующий glDisableVertexAttribArray()
s после вашего розыгрыша:
glEnableVertexAttribArray(positionA);
if(hasTexture) glEnableVertexAttribArray(texcoordA);
// draw
glDisableVertexAttribArray(positionA);
if(hasTexture) glDisableVertexAttribArray(texcoordA);
Проблема в том, что я включил массивы атрибутов вершин после компиляции моего шейдера. Это не то место, где я должен был их разрешить.
Я включил атрибут texcoord при компиляции шейдера, но так как первый элемент не использовал его, glDrawElements будет работать с ошибкой.
Я исправил это, включив атрибут при настройке шейдера.