#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