Проблемы при попытке применить шейдер к массиву вершин в OpenGL с использованием C ++ - PullRequest
1 голос
/ 12 октября 2011

У меня есть 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;
}

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

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

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.

Edit 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;
}

1 Ответ

2 голосов
/ 12 октября 2011

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

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

EDIT: Из вашего обновления кажется, что вы не используете специальный фрагментный шейдер. Таким образом, вы просто используете встроенный фрагментный конвейер вместе с вашим вершинным шейдером. В то время как это возможно, вам все равно придется совмещать оба этапа для совместной работы. Ваше passcolor изменение совершенно бесполезно, так как конвейер с фиксированной функцией не знает, что с ним делать. Просто используйте изменяющийся цвет buitlin и замените

passcolor = gl_Color;

с

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

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

...