В моей программе OpenGL ES 2.0 на iOS я компилирую свои шейдеры следующим образом:
setShaderState(state);//enables or disables GL_BLEND
GLuint vertexShader = compileShaderPart(vertexShader, GL_VERTEX_SHADER, state);
GLuint fragmentShader = compileShaderPart(fragmentShader, GL_FRAGMENT_SHADER, state);
//linking
GLuint programHandle = glCreateProgram();
Assert(programHandle != 0, "Program handle 0");
for(auto shaderAttribute : shaderAttributeList){
if(isVertexAttribute(shaderAttribute.attribute())){
glBindAttribLocation(programHandle, shaderAttribute.attribute(), shaderAttribute.attributeName(1).c_str());
}
}
glAttachShader(programHandle, vertexShader);
glAttachShader(programHandle, fragmentShader);
glLinkProgram(programHandle);
Assert(glGetError() == GL_NO_ERROR, "Could not link program");
GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE) {
GLchar messages[256];
glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
ELog << messages;
Assert(0, "Error compiling shader");
}
ShaderUniformHandleMap shaderUniformMap;
Shader *shader = new Shader(programHandle, availableShader.name, shaderUniformMap, state);
glUseProgram(programHandle);
auto mesh = Mesh::load("quad");
shader->bindMesh(mesh);
auto temp_texture = Texture2D::load("checker");
for(auto uniform : shader->texture){
glUniform1i(uniform.handle, shader->bindTexture(temp_texture->textureId()));
}
glDrawElements(GL_TRIANGLES, mesh->indexDataSize(), GL_UNSIGNED_SHORT, 0);
Я исключил унифицированную часть чтения для удобочитаемости, а функция compileShaderPart настолько прямолинейна, насколько это возможно.
Запуск приложения в openGL ES Analyzer в инструментах приводит к сотням случаев возникновения проблемы «Шейдер, скомпилированный вне фазы предварительного прогрева». Разве вызов glDrawElements не должен позаботиться об этом?
Я читал, что изменение состояний, таких как GL_Blend, может иметь такое влияние, поэтому я компилирую один и тот же шейдер дважды, один раз с включенным GL_Blend и один раз с отключенным, но это не имело никакого значения.
В чем проблема? Мне также трудно найти информацию об этом предварительном прогреве, пока я понял, что шейдер действительно компилируется только после первого вызова отрисовки, поэтому я рисую этот четырехугольник в конце.