Я пишу базовый менеджер представлений, используя GL на ubuntu 13 и eeepc с nvidia ION2 (оптимизатор, использующий проект шмеля). У меня есть XML файл, из которого создаются шейдеры, когда система запускается (например, плагины) и добавляется в словарь. Как только они скомпилированы, связаны и готовы к использованию, для выбора подходящей шейдерной программы на основе переданного имени программы используется функция обертки.
void ShadingProgramManager::useProgram(const std::string& program){
GLuint id = getProgramId(program);
glUseProgram(id);
if(GL_INVALID_VALUE == glGetError() || GL_INVALID_OPERATION == glGetError()){
printf("Problem Loading Shader Program");
return;
}
printf("%s is in use", program.c_str());
}
Где getProgramId просто просматривает предварительно созданный словарь и возвращает идентификатор шейдерной программы.
Когда я визуализую объект, я использую эту программу, вызывая:
ShadingProgramManager::getInstance()->useProgram('vc');
'vc' формируется из следующих шейдеров
Vertex Shader - vc.vert
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
out vec4 vertcolor;
void main(){
vertcolor = color;
gl_Position = vec4(position, 1.0); //I've tried setting this as position * 10 also for any apparent changes on screen, but nothing changes
}
Фрагмент Shader - vc.frag:
#version 330
in vec4 vertcolor;
out vec4 outputcolor;
void main(){
outputcolor = vertcolor;
}
Мой буфер вершин чередуется как:
VertexColor vertices[] =
{
{-1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 1.0}, /*first 3 floats for pos, 4 for color */
{ 1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0},
{ 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0},
{-1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0},
};
Буфер индексов:
GLuint indices[] =
{
0, 1, 2,
0, 2, 3,
};
VertexColor определяется как:
class VertexColor{
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat r;
GLfloat g;
GLfloat b;
GLfloat a;
/** some constants as below **/
};
const int VertexColor::OFFSET_POSITION =0;
const int VertexColor::OFFSET_COLOR =12;
const int VertexColor::SIZE_POSITION =3;
const int VertexColor::SIZE_COLOR =4;
const int VertexColor::STRIDE =28;
Затем я использую следующий код для рендеринга quad:
ShadingProgramManager::getInstance()->useProgram('vc');
glBindBuffer(GL_ARRAY_BUFFER, &vb);
glBufferData(GL_ARRAY_BUFFER, size_of_vertices_array, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, &ib);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_of_indices_array, indices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribArrayPointer(0, VertexColor::SIZE_POSITION, GL_FLOAT, GL_FALSE, VertexColor::STRIDE, (GLvoid*)VertexColor::OFFSET_POSITION);
glVertexAttribArrayPointer(1, VertexColor::SIZE_COLOR, GL_FLOAT, GL_FALSE, VertexColor::STRIDE, (GLvoid*)VertexColor::OFFSET_COLOR);
glDrawElements(GL_TRIANGLES, size_of_indices, GL_UNSIGNED_INT, 0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
Тем не менее, я вижу только белый квадрат. Я подозреваю, что это исправный трубопровод, который вступает в силу.
Даже если я удалю вызов glUseProgram (id) или использую glUseProgram (0), я все равно получаю те же результаты. Я также попытался умножить позицию в вершинном шейдере на 10.0, но не повлиял на экран. Я уверен, что шейдеры также скомпилированы и связаны. Когда я перехожу к использованию чего-то вроде glUseProgram (40) или любого недопустимого числа, я получаю необходимые сообщения об ошибках, но, как правило, вижу только белый квадрат!
Извините за навязчиво длинный пост, но я в тупике на этом... Я просто получаю белый квадрат квадрата, независимо от того, какие изменения я делаю с вершинным или фразовым шейдером. Я подозреваю, что GL по умолчанию выполняет FFP, и по какой-то причине моя шейдерная программа не вступает в силу. Я надеюсь, что это ошибка noobish, но любые указатели будут оценены.
PS: Нет ошибок компиляции, поэтому, пожалуйста, извините за любые синтаксические ошибки в коде. Я набрал полный код выше.
UPDATE: я добавил последний параметр в вызов glVertexAttribArrayPointer, как это было предложено Андоном, Динешем и Спектром, и я пропустил ранее, но все тот же результат.
Задача решена.
Да, это была ошибка noobish, но все ваши комментарии помогли мне пробежать весь код еще раз. Я начал переделывать все с помощью FFP и перешел на PFP. Итак, вот ошибка:
Я пропустил установку glAttachShader(pid, sid)
в словаре, который был создан для шейдерных программ, поэтому, когда программа действовала, вершинный шейдер и шейдер-фрагмент никогда не применялись.
Посмотрите на эту строку
glVertexAttribArrayPointer(1, VertexColor::SIZE_COLOR, GL_FLOAT, GL_FALSE, VertexColor::STRIDE);
Где находится указатель Задает смещение первого компонента первого общего атрибута вершины в массиве. В вашем вершинном массиве данные цвета начинаются с 4-го положения. Вы должны указать начальную позицию первого компонента данных цвета. Начальное значение указателя равно 0, поэтому программа считывает данные цвета из первой позиции в позицию 4, которая не является цветовыми данными. Но он правильно считывает вершинные данные, потому что программа считывает данные вершин из первой позиции в третью позицию, которая является правильным значением. Таким образом, вы видите только белый квадрат.