Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OpenGL ES 1и2.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
4.8 Mб
Скачать

Получение матриц.

Чтобы передать матрицу модели-вида-проекции u_modelViewProjectionMatrix в вершинный шейдер нужно ее получить. Матрица модели.

Матрица модели описывает собственное движение вершин, из которых состоит модель, в трехмерном пространстве. Простейший случай модели - это одна вершина. Рассмотрим для примера поворот. Например, нам нужно повернуть вершину с координатами x,y,z вершину на угол angle против часовой стрелки относительно вектора с координатами rotateVectorX, rotateVectorY, rotateVectorZ, проходящего через начало координат. Для определения матрицы поворота существует команда Matrix.setRotateM. Получим матрицу поворота modelMatrix.

Определим пустой массив для матрицы модели:

float[] modelMatrix = new float[16];

Применим команду: 

Matrix.setRotateM(modelMatrix, 0, angle, rotateVectorX, rotateVectorY, rotateVectorZ);

Получим заполненный массив modelMatrix, соответствующий нашему повороту.

Как получить новые координаты вершины после поворота? Достаточно умножить матрицу модели на вектор координат вершин:

//запишем текущие координаты вершин в четырехкомпонентный вектор float vertex[]={x,y,z,1}; //создадим пустой массив, в который будут записаны новые координаты

float new_vertex=new float[4]; //умножим матрицу модели на вектор координат Matrix.multiplyMV(new_vertex, 0, modelMatrix, 0, vertex, 0); //получили новые координаты после поворота float new_x=new_vertex[0]; float new_y=new_vertex[1]; float new_z=new_vertex[2];

Команда Matrix.multiplyMV умножает матрицу модели modelMatrix на вектор координат вершины vertex и записывает результат в массив new_vertex. Если модель состоит из множества  жестко связанных вершин, совершающих одинаковую трансформацию, нужно умножить матрицу модели на координаты каждой вершины. Если вершин несколько тысяч - это может быть затратно по времени, если трансформации вершин производить на CPU. Поэтому, в этом случае удобнее передать матрицу модели в вершинный шейдер как униформу и преобразования координат вершин выполнять в вершинном шейдере. Если вершин немного, можно оставить расчет модельных трансформаций вне шейдера.

Матрица вида.

Матрица вида однозначно связана с координатами камеры. Зная положение и ориентацию камеры мы можем всегда получить матрицу вида. Для этого в классе android.opengl.Matrix существует специальная функция Matrix.setLookAtM. 

Определим пустой массив для матрицы вида:

float[] viewMatrix = new float[16];

Зададим положение камеры пространстве для примера:

float xposition=0.3f;

float yposition=1.7f;

float zposition=1.5f;

Зададим точку в пространстве, на которую смотрит камера. Пусть камера смотрит на начало мировых координат:

float xlook=0;

float ylook=0;

float zlook=0;

Для однозначного определения матрицы вида этих данных мало, т.к. недостаточно установить наблюдателя в точку и правильно направить его взгляд. Нужно еще запретить наблюдателю качать головой. Зададим вектор, который определит, где у камеры верх. Пусть верх будет вдоль оси Y:

float xtop=0;

float ytop=1;

float ztop=0;

А затем вызовем функцию функция Matrix.setLookAtM, которая рассчитает и заполнит  массив viewMatrix:   

Matrix.setLookAtM(viewMatrix, 0, xposition, yposition, zposition, xlook, ylook, zlook, xtop, ytop, ztop);

Матрица вида готова.

Матрица модели-вида. Часто комбинируют матрицы модели и вида в единую матрицу модели-вида, которую можно получить путем умножения матрицы вида на матрицу модели. Для умножения двух матриц используют команду Matrix.multiplyMM. float[] modelViewMatrix = new float[16]; Matrix.multiplyMM(modelViewMatrix, 0, viewMatrix, 0, modelMatrix, 0); Получили заполненный массив modelViewMatrix.

Матрица проекции.

Матрица проекции выполняет проекцию координат вершин на экран аппарата после модельно-видовых трансформаций. Она может получена в методе onSurfaceChanged  класса рендерера путем выполнения команды Matrix.frustumM для перспективной проекции. Например, так:

............ float projectionMatrix=new float[16]; ............ public void onSurfaceChanged(GL10 unused, int width, int height) {        // устанавливаем glViewport        GLES20.glViewport(0, 0, width, height);        float ratio = (float) width / height;        float k=0.055f;        float left = -k*ratio;        float right = k*ratio;        float bottom = -k;        float top = k;        float near = 0.1f;        float far = 10.0f;        // получаем матрицу проекции       Matrix.frustumM(projectionMatrix, 0, left, right, bottom, top, near, far); } Матрица модели-вида-проекции. Умножив матрицу проекции на матрицу модели-вида получаем комбинированную матрицу модели-вида-проекции: float modelViewProjectionMatrix=new float[16]; Matrix.multiplyMM(modelViewProjectionMatrix,0,projectionMatrix, 0, modelViewMatrix, 0);

Матрица модели-вида-проекции получена. Напомню, что  матрица модели-вида-проекции передается в вершинный шейдер как униформа. Вопрос по передаче данных униформ в шейдеры будет рассмотрен позже.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]