Я должен признать, что я впервые использую шейдеры, ранее я работал только с конвейером фиксированных функций; однако, хотя я уверен, что все, что я сделал, правильно - должна быть ошибка.
glLinkProgram(program)
- возвращает GL_FALSE
при запросе GL_LINK_STATUS
. Кроме того, информационный журнал пуст (когда я запрашиваю длину журнала - она равна 1, что является нулевым терминатором для документов, оно проверяется). Так что ошибки компоновщика, а не логи. Кроме того, я только что обнаружил, что проблемы с компоновщиком возникают, как только я использую переменную gl_Position
в вершинном шейдере, как при назначении, так и при использовании его для вычислений. Я перепробовал всевозможные варианты шейдеров, он выдает ошибки, но он не выдает журналы - он просто возвращает GL_FALSE
каждый раз, когда gl_Position
затрагивается. Интересно, что фрагментный шейдер не вызывает проблем.
Фрагментные и вершинные шейдеры прекрасно компилируются без ошибок. Когда я ввожу синтаксические ошибки, они обнаруживаются, печатаются, и процесс прерывается перед созданием программы (так что, похоже, он работает нормально). Я отладил и удостоверился, что файлы загружаются правильно, источник завершен нулем, размеры правильные, я проверил количество вложенных программ после вложения, и оно равно 2 (правильно lol). Это удалено для ясности, у меня есть метод checkForErrors()
, который проверяет и печатает ошибки opengl - ни один не обнаружен.
Я в тупике, пожалуйста, помогите кому-нибудь! Я терял сон из-за этого уже 2 дня ...
Это код для загрузки шейдера:
FILE *file = fopen(fileName.c_str(), "rb");
if(file == NULL)
{
Log::error("file does not exist: \"" + fileName + "\"");
return NULL;
}
// Calculate file size
fseek(file , 0 , SEEK_END);
int size = ftell(file);
rewind(file);
// If file size is 0
if(size == 0)
{
Log::error("file is empty: \"" + fileName + "\"");
return NULL;
}
char **source = new char*[1];
source[0] = new char[size+1];
source[0][size] = '\0';
// If we weren't able to read the entire file into memory
int readSize = fread(source[0], sizeof(char), size, file);
if(size != readSize)
{
int fileError = ferror(file);
// Free the source, log an error and return false
delete source[0];
delete [] source;
fclose(file);
Log::error("couldn't load file into memory [ferror(" + toString<int>(fileError) + ")]: \"" + fileName + "\" (Size: " + toString<int>(readSize) + "/" + toString<int>(size) + " bytes)");
return NULL;
}
// Close the file
fclose(file);
// Create the shader object
// shaderType is GLenum that is set based on the file extension. I assure you it is correctly set to either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER
GLuint shaderID = glCreateShader(shaderType);
// If we could not create the shader object, check for OpenGL errors and return false
if(shaderID == 0)
{
checkForErrors();
Log::error("error creating shader \"" + name);
delete source[0];
delete [] source;
return NULL;
}
// Load shader source and compile it
glShaderSource(shaderID, 1, (const GLchar**)source, NULL);
glCompileShader(shaderID);
GLint success;
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
if(!success)
{
GLchar error[1024];
glGetShaderInfoLog(shaderID, 1024, NULL, error);
Log::error("error compiling shader \"" + name + "\"\n Log:\n" + error);
delete source[0];
delete [] source;
return NULL;
}
else
{
Log::debug("success! Loaded shader \"" + name + "\"");
}
// Clean up
delete source[0];
delete [] source;
Краткое примечание: glShaderSource - я приводил (const GLchar **), потому что GCC жалуется на const на неконстантные указатели на символы; В противном случае, я считаю, что я полностью податлив.
Никаких ошибок там, кстати. Шейдеры (ниже) компилируются без ошибок.
Вершинный шейдер:
void main()
{
// If I comment the line below, the link status is GL_TRUE.
gl_Position = vec4(1.0, 1.0, 1.0, 1.0);
}
Фрагмент шейдера:
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Ниже приведен код, который создает шейдерную программу, присоединяет объекты и ссылки и т. Д.:
// Create a new shader program
GLuint program = glCreateProgram();
if(program == 0)
{
Log::error("RenderSystem::loadShaderProgram() - could not create OpenGL shader program; This one is fatal, sorry.");
getContext()->fatalErrorIn("RenderSystem::loadShaderProgram(shader1, shader2)", "OpenGL failed to create object using glCreateProgram()");
return NULL;
}
// Attach shader objects to program
glAttachShader(program, vertexShaderID);
glAttachShader(program, fragmentShaderID);
// Link the program
GLint success = GL_FALSE;
glLinkProgram(program);
checkForErrors();
glGetProgramiv(program, GL_LINK_STATUS, &success);
if(success == GL_FALSE)
{
GLchar errorLog[1024] = {0};
glGetProgramInfoLog(program, 1024, NULL, errorLog);
Log::error(std::string() + "error linking program: " + errorLog);
return NULL;
}
success = GL_FALSE;
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &success);
if(success == GL_FALSE)
{
GLchar errorLog[1024] = {0};
glGetProgramInfoLog(program, 1024, NULL, errorLog);
checkForErrors();
Log::error(std::string() + "error validating shader program; Details: " + errorLog);
return NULL;
}
Обычно это даже не так далеко, как проверка программы ... Я так расстроен этим, очень трудно не быть вульгарным.
Ваша помощь необходима, и любая помощь искренне ценится!
РЕДАКТИРОВАТЬ: я все работаю на Intel HD 3000 (с поддержкой OpenGL до 3.1). Моя целевая версия OpenGL - 2.0.
EDIT2: Я также хотел бы отметить, что у меня возникли некоторые проблемы с чтением шейдеров из текстовых файлов, если я установил флаги «r» или «rt» в fopen - размер чтения был меньше, чем фактический размер, примерно на 10 байт. (последовательно для всех файлов) - и feof () вернет true. Когда я переключился на чтение в двоичном формате («rb»), проблема исчезла, и файлы были прочитаны полностью. Я попробовал несколько альтернативных реализаций, и все они выдавали одну и ту же ошибку при связывании (и я печатаю исходный код шейдера на консоль сразу после чтения файла, чтобы убедиться, что он выглядит правильно.).