Как использовать glUniform1f в этом примере?

#java #android #opengl-es #textureview

#java #Android #opengl-es #textureview

Вопрос:

Я искал, читал и пробовал множество различных примеров того, как передать значение в программу GLSL. Но, к сожалению, каждая попытка заканчивалась неудачей:(

То, что я планирую сделать, очень просто: просто немного открыть 3d-анимацию gl в моем приложении для Android. В результате моего дизайна графического интерфейса я предпочитаю использовать TextureView в качестве поверхности OpenGL. Я нашел некоторый код, который идеально подходит для моего проекта.

Но моя проблема, похоже, полностью находится внутри этого примера.

Когда я компилирую и запускаю его, он делает именно то, что должен делать. Нарисуйте на экране один-единственный треугольник.

Затем я модифицировал вершинный шейдер следующим образом:

 final String vertexShaderSource = 
   "attribute vec4 position;n"  
   "attribute float myValue;n"  
   "void main () {n"  
         "vec4 oo;n" 
         "oo[0] = position[0];n" 
         "oo[1] = position[1] * myValue;n" 
         "oo[2] = position[2];n" 
         "oo[3] = position[3];n" 
         "gl_Position = oo;n"  
   "}";
  

И теперь я хочу передать значение атрибуту myValue .

Итак, вот мои модификации метода run.

 public void run() {
   initGL();

   int attribPosition = GLES20.glGetAttribLocation(mProgram,
           "position");
   checkGlError();

   int valuePosition = GLES20.glGetAttribLocation(mProgram,
           "myValue");
   checkGlError();

   System.out.println("att id:"  attribPosition 
             " val id:"   valuePosition);

//[...]

   while (true) {
       checkCurrent();

       mVertices.position(0);
       GLES20.glVertexAttribPointer(attribPosition, 3,
                 GLES20.GL_FLOAT, false, 0, mVertices);
       checkGlError();

       GLES20.glUniform1f(valuePosition, 1.5f);
       checkGlError();
    //[...]           
    }
}
  

Насколько я понимаю, это должно расширить треугольник по оси y с коэффициентом 1.5f. Но это не работает.
Вывод моей строки отладки:

 I/System.out(22427): att id:1 val id:0
  

Таким образом, это должны быть правильные местоположения, поскольку ни одно из них не имеет содержимого -1.
Но, передавая значение 1.5f в myValue с glUniform1f помощью OpenGL Error 0x502 , единственный результат, которого я могу достичь, — это непрерывный не прерывающийся вывод. Треугольника больше нет, потому что шейдерный скрипт не получит 1.5f и будет использовать значение 0 для его расширения.

Я действительно надеюсь, что кто-нибудь сможет объяснить мне, как это сделать. Поскольку это нечто настолько фундаментальное, я думаю, что упускаю здесь что-то очень очевидное.

Комментарии:

1. Проверьте, не возникает ли какая-либо ошибка OpenGL во время выполнения вашего шейдера, и обновите вопрос с ее помощью.

2. Других ошибок OpenGL нет. И в примере много проверок на наличие ошибок.

Ответ №1:

Вы смешиваете понятия attribute и uniform переменных.

Поскольку вы объявили свою myValue переменную как attribute в шейдере, вам нужно задать значение с помощью glVertexAttrib() :

 glVertexAttrib1f(valuePosition, 1.5f);
  

Если вы хотите, чтобы это было uniform , измените объявление в вершинном шейдере на:

 uniform float myValue;
  

и звонок, чтобы узнать местоположение, чтобы:

 int valuePosition = GLES20.glGetUniformLocation(mProgram, "myValue");
  

Оба решения допустимы. Как следует из названия, uniform переменные идеально подходят для значений, которые не сильно меняются, т. Е. в идеале они остаются неизменными для всего фрейма. attribute переменные более эффективны для значений, которые часто меняются при рендеринге фрейма.

Ответ №2:

Вам нужно объявить форму, прежде чем задавать ее через glUniform1f . Итак, сделайте myValue как единообразный.

 uniform float myValue;
  

Следующее, что вам нужно, это его местоположение для привязки значения. Вы можете сделать это с помощью glGetUniformLocation функции.

 int valuePosition = GLES20.glGetUniformLocation(mProgram, "myValue");
  

И, наконец, вы устанавливаете форму для этого местоположения с помощью glUniform функций.

 GLES20.glUniform1f(valuePosition, 0.5f);
  

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

Ответ №3:

Попробуйте изменить следующее:

"attribute float myValue;n"
->
"uniform float myValue;n"

и

int valuePosition = GLES20.glGetAttribLocation(mProgram, "myValue"); -> int valuePosition = GLES20.glGetUniformLocation(mProgram, "myValue");

Кроме того, взгляните на следующую страницу документации, которая показывает более чистый способ перевода и масштабирования вершин.

http://developer.android.com/reference/android/opengl/Matrix.html