#android #c #matrix #opengl-es #projection
#Android #c #Матрица #opengl-es #проекция
Вопрос:
Я рисую простой четырехъядерный процессор, используя gles2.0 на c . Если я нарисую его с помощью базового вершинного шейдера, проблем не возникнет, и это результат
uniform mat4 u_mvp;
attribute vec4 a_Position;
void main(){
gl_Position = a_Position;
}
если я добавлю матрицу MVP
gl_Position = u_mvp * a_Position;
тогда на экране ничего нет.
Это и есть перспективная матрица:
Matrix4 Matrix4::getPerspective(float angle, float ratio, float near, float far) {
// angle = 45; ratio = 1.438; near = 1; far = 100
Matrix4 matrix;
float top = (float)(near * Math::tangentDegrees(angle / 2.0f));
float bottom = -top;
float right = top * ratio;
float left = -right;
matrix.m[0] = (2 * near) / (right - left);
matrix.m[1] = 0.0f;
matrix.m[2] = (right left) / (right - left);
matrix.m[3] = 0.0f;
matrix.m[4] = 0.0f;
matrix.m[5] = (2 * near) / (top - bottom);
matrix.m[6] = (top bottom) / (top - bottom);
matrix.m[7] = 0.0f;
matrix.m[8] = 0.0f;
matrix.m[9] = 0.0f;
matrix.m[10] = -(far near) / (far - near);
matrix.m[11] = -(2 * far * near) / (far - near);
matrix.m[12] = 0.0f;
matrix.m[13] = 0.0f;
matrix.m[14] = -1.0f;
matrix.m[15] = 0.0f;
return matrix;
}
Матрица ModelView получается следующим образом:
modelView = translation * rotation * scale
mvp = perspective * modelView
Каждый элемент этого умножения выполняется в следующем примере
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices /
и все они инициализируются в матрице идентификаторов.
С помощью этой команды я получаю дескриптор
transformUniformHandle = (GLuint)glGetUniformLocation(getProgramId(), "u_mvp");
С помощью этой команды я установил матрицу mvp в шейдере (пробовал оба GL_FALSE, GL_TRUE)
glUniformMatrix4fv(transformUniformHandle, 1, GL_TRUE, modelViewProjection.m);
Ответ №1:
OpenGL использует хранилище по основным столбцам для матриц, в то время как ваша проекционная матрица настраивается в порядке следования строк. Итак, вам нужно перенести порядок элементов матрицы:
matrix.m[0] = (2 * near) / (right - left);
matrix.m[4] = 0.0f;
matrix.m[8] = (right left) / (right - left);
matrix.m[12] = 0.0f;
matrix.m[1] = 0.0f;
matrix.m[5] = (2 * near) / (top - bottom);
matrix.m[9] = (top bottom) / (top - bottom);
matrix.m[13] = 0.0f;
matrix.m[2] = 0.0f;
matrix.m[6] = 0.0f;
matrix.m[10] = -(far near) / (far - near);
matrix.m[14] = -(2 * far * near) / (far - near);
matrix.m[3] = 0.0f;
matrix.m[7] = 0.0f;
matrix.m[11] = -1.0f;
matrix.m[15] = 0.0f;
Вы пытались перенести матрицу, передав GL_TRUE
ее в качестве 3-го аргумента здесь:
glUniformMatrix4fv(transformUniformHandle, 1, GL_TRUE, modelViewProjection.m);
Это не поддерживается в ES 2.0, единственным допустимым значением аргумента является GL_FALSE
. GL_INVALID_VALUE
При вызове glGetError()
после этого вы увидите сообщение об ошибке. Вызов glGetError()
должен быть обычным, если у вас возникли проблемы с вашим кодом OpenGL.
Вы могли бы сохранить основную строку матрицы, если бы действительно захотели, и соответствующим образом изменить код шейдера, умножив вектор справа:
gl_Position = a_Position * u_mvp;
Но, вероятно, лучше просто использовать порядок следования столбцов для ваших матриц.
Кроме того, вы не показываете свою матрицу представления модели. Вам нужно будет убедиться, что преобразование вида преобразует геометрию в отрицательном направлении z, чтобы она располагалась между ближней и дальней плоскостями используемого вами преобразования проекции.
Ответ №2:
Учитывая, что вы не показали весь свой код, я не могу быть уверен, но, возможно, вы не вызывали glUseProgram перед вызовом glUniformMatrix4fv. Также может случиться так, что ваши треугольники вырезаны матрицей проекции. Убедитесь, что точки находятся в пределах диапазона отсечения. Если это не исправит проблему, вы должны получать ошибки от glGetError. На этой странице будет объяснено его использование: проверка ошибок OpenGL
Комментарии:
1. Спасибо за ваш ответ. Я не могу опубликовать весь код, потому что объектов много, и это будет очень много. Вызывается glUseProgram, на самом деле код работает, если я не использую mvp.