Проблемы при попытке применить шейдер к массиву вершин в OpenGL с использованием C ++

У меня есть 4-мерные вершины (X, Y, A, B), которые я хотел бы нарисовать как 6 отдельных 2D-графиков (XxY, XxA, XxB, YxA, ...)

Мои вершины определены следующим образом:

GLint data[MAX_N_POINT][4];

Я могу легко нарисовать первый (X, Y) из 2D-графиков с помощью:

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_INT, 4*sizeof(GLint), &data[0][0]);

glDrawArrays(GL_POINTS, 0, MAX_N_POINT-1);
glDisableclientState(GL_VERTEX_ARRAY);

Чтобы нарисовать другие 2D-графики (XxA, AxB и т. Д.), Я решил использовать шейдер, который меняет размеры X, Y, Z, W вершин в зависимости от того, какие размеры я хочу нарисовать:

uniform int axes;

void main()
{

vec2 point;
if (axes == 0) {
   point = gl_Vertex.xy;
} else if (axes == 1) {
   point = gl_Vertex.xz;
} else if (axes == 2) {
   point = gl_Vertex.xw;
} else if (axes == 3) {
   point = gl_Vertex.yz;
} else if (axes == 4) {
   point = gl_Vertex.yw;
} else if (axes == 5) {
   point = gl_Vertex.zw;
}

gl_Position = gl_ModelViewProjectionMatrix * vec4(point.xy, 0.0, 1.0);

gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}

Я успешно загрузил, скомпилировал, добавил шейдер в программу и связал программу.

Теперь, когда у меня есть программа шейдера, неясно, как использовать программу, так как это влияет на способ рисования моих массивов вершин. Я пробовал следующее, но, похоже, это не дало никакого эффекта, так как он рисует вещи точно так же, как и без шейдера:

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_INT, 4*sizeof(GLint), &data1[0][0]);

//New shader code here
glUseProgram(shaderProg);
int plotAxes = rand()%4;
GLint axes = glGetUniformLocation(shaderProg, "axes"); 
glUniform1i(axes, plotAxes);

glDrawArrays(GL_POINTS, 0, MAX_N_POINT-1);
glDisableClientState(GL_VERTEX_ARRAY);  
glUseProgram(0);

Есть ли что-то фундаментальное, что я упускаю или не понимаю должным образом?

Редактировать 2: я обновил код шейдера в соответствии с предложениями Кристиана. Я также убедился, что оттенок загружается без ошибок, однако, если я проверю наличие ошибок OpenGl после вызова glUseProgram, я получаю сообщение об ошибке OpenGL Error: invalid operation.

Редактировать 3: вот последний шейдер, который сработал:

uniform int axes;

void main()
{
  vec4 point; 
  if (axes == 0) {
     point = gl_Vertex; 
  } else if (axes == 1) {
     point = gl_Vertex.xzyw; 
  } else if (axes == 2) {
     point = gl_Vertex.xwzy; 
  } else if (axes == 3) {
      point = gl_Vertex.yzxw; 
  } else if (axes == 4) {
     point = gl_Vertex.ywxz; 
  } else if (axes == 5) {
     point = gl_Vertex.zwxy; 
  }

  point.z = 0.0; 
  point.w = 1.0; 

  // eliminate w point
  gl_Position = gl_ModelViewProjectionMatrix * point;

    gl_FrontColor = gl_Color;
    gl_BackColor = gl_Color;
}

person slayton    schedule 12.10.2011    source источник
comment
Я не уверен, почему ваш шейдер не работает, но почему бы не использовать другие матрицы представления модели вместо того, чтобы делать большой if в вашем шейдере?   -  person user786653    schedule 12.10.2011
comment
Мне интересно, возможно, мой шейдер загружен неправильно. Хотя при запуске своей программы он не вызывает никаких ошибок.   -  person slayton    schedule 12.10.2011
comment
@ user786653 Хорошее замечание. Но я не вижу, где вы могли бы создать w-компонент 1 из ниоткуда, используя простое умножение матрицы на вектор, поскольку все четыре компонента его вектора используются для данных.   -  person Christian Rau    schedule 12.10.2011
comment
@ChristianRau: Хм, да, похоже, для этого также потребуется поддержка вершинных шейдеров.   -  person user786653    schedule 12.10.2011


Ответы (1)


Вы должны установить axes униформу (glUniform1i) после того, как вы включили / использовали программу (glUseProgram), иначе это не даст никакого эффекта (а ваша axes униформа сохраняет значение по умолчанию, которое кажется равным 0). Но я надеюсь, что ваша программа также содержит действующий шейдер фрагмента, который использует ваше passcolor варьирование, поскольку процессор фрагментов с фиксированной функцией не знает, что делать с этим изменением.

И, кстати, хотя это не будет стоить вам так дорого, если все вершины все равно пойдут по одному и тому же пути, но использование 6 разных шейдеров было бы лучшей идеей с точки зрения производительности. Вы по-прежнему можете использовать макросы препроцессора, чтобы уменьшить накладные расходы на запись.

РЕДАКТИРОВАТЬ: Судя по вашему обновлению, вы не используете специальный шейдер фрагментов. Таким образом, вы просто используете встроенный конвейер фрагментов вместе со своим вершинным шейдером. Хотя это возможно, вам все равно придется совместить оба этапа, чтобы работать вместе. Ваше passcolor варьирование совершенно бесполезно, поскольку конвейер фиксированных функций не знает, что с ним делать. Просто используйте другой цвет buitlin и замените

passcolor = gl_Color;

с участием

gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;       //just to be sure

Вы также должны проверить, успешно ли компилируются и связываются ваши шейдеры, и проверять информационный журнал, если они этого не делают, поскольку я полагаю, ваша программа не будет связываться из-за вышеупомянутых различных несоответствий. Таким образом, вы в конечном итоге не используете шейдер (и с кучей GL_INVALID_OPERATIONs), не замечая этого.

person Christian Rau    schedule 12.10.2011
comment
Хороший улов. Обычно я бы рекомендовал OP всегда проверять возвращаемые значения / glGetError, но с OGL это такая боль .. Что-то вроде glintercept удобен. - person user786653; 12.10.2011
comment
Хорошо, я переместил glUseProgram над строкой, в которой я определяю переменную axes, но, увы, это не повлияло. - person slayton; 12.10.2011
comment
@slayton Смотрите мое обновление. Кажется, вы все равно молча не используете шейдер. - person Christian Rau; 12.10.2011
comment
@ChristianRau, спасибо, я обновил шейдер и включил проверку ошибок в рисунок. Я получаю OpenGL Error: invalid operation ошибку - person slayton; 12.10.2011
comment
Хорошо, у меня все заработало, я немного изменил код шейдера. Спасибо за вашу помощь. Я бы не заработал, если бы не бит о цвете пароля. - person slayton; 12.10.2011
comment
@slayton Я бы посоветовал не перезаписывать код вопроса (неправильный код) как для приложения, так и для кода шейдера. Это сбивает с толку людей, которые позже видят этот вопрос, поскольку теперь нигде нет ошибки. Если хотите, лучше добавьте правильный код в свой вопрос. И спасибо, что приняли. - person Christian Rau; 12.10.2011