Я надеюсь, что кто-то может помочь мне понять GLViewport и что произойдет, когда мы изменим его размер
Это проиллюстрирует мою путаницу ....
Итак, здесь я застрял в середине экрана. Если мой GLViewport соответствует ширине и высоте устройства, я получаю то, что находится на первом (левом) изображении. Именно то, что я ожидал.
- Разрешение устройства, 2560 х 1600
- Разрешение области просмотра 2560 x 1600
- Квадратный размер 200 х 200 (Обратите внимание, что изображение выше не в масштабе !!! :-))
- Квадратная форма, выглядит как квадрат
Теперь для второй (правой руки) картинки ...
- Разрешение устройства, 2560 х 1600
- Разрешение области просмотра 2560 x 1200 (по центру по вертикали)
- Квадратный размер (200, 200)
- Четырехугольная форма, выглядит как прямоугольник
Мой вопрос: почему квад теперь отображается в виде прямоугольника, а не квадрата? В журнале я подтвердил, что мой квадроцикл имеет размер 200 x 200 пикселей - конечно, размер физических пикселей остается неизменным? Они не могут измениться. и так, что здесь происходит?
Я думал (явно неправильно), что когда я масштабировал область просмотра, она буквально отсекала пиксели.
Был бы признателен, если бы кто-то мог объяснить, как это работает.
редактировать
В настоящее время я настраиваю свой видовой экран следующим образом:
width = (int) Math.min(deviceWidth, deviceHeight * 1.702127659574468);
height = (int) Math.min(deviceHeight, deviceWidth / 1.702127659574468);
ratio = width / height;
GLES20.glViewport(offsetX, offsetY, width, height);
Matrix.orthoM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
offsetX и offsetY таковы, что при наличии почтовых ящиков область просмотра центрируется.
источник
glScissor
вместо этогоglViewport
, он будет просто обрезать пиксели, не меняя, где что-либо отображается.glViewport
ведет себя больше как изменение исходного изображения, а не как его обрезка; вот почему это раздавливает вашу коробку.Ответы:
Чтобы понять, что происходит, вы должны понять конвейер рендеринга:
Ваша геометрия (квад) изначально определена в мировом пространстве, представьте это как некоторую глобальную систему координат. Внутри вершинного шейдера они преобразуются в нормализованные координаты устройства (NDC), виртуальную систему координат, определенную так, что все от -1 до 1 будет отображаться на экране. Обратите внимание, что значение NDC составляет от -1 до 1 в X и Y, и оно полностью не зависит от соотношения сторон и разрешения устройства. Это преобразование из мирового пространства в НДЦ осуществляется с помощью модели, матрицы представления и проекции (в простой форме, для начала была задана всего одна матрица для всего или геометрия в НДЦ!).
Модуль растеризации должен знать, где и как велик растр, и это то, что вы определяете с помощью вызова glViewport: с чего начать - первые два параметра, а размер - вторые два. Аппаратные средства затем преобразуют из NDC в пиксельные координаты простым масштабом и смещением - и это то, что вы видите в своем примере: масштаб по оси Y.
Таким образом, чтобы убедиться, что ваш четырехугольник отображается в правильном соотношении сторон, вам также нужно настроить матрицу проекции, чтобы включить ожидаемое соотношение сторон вызова glViewport.
источник
glFrustum
список точной матрицы, которая создается этими функциями. Другая распространенная матрица проекций, которую вы, возможно, захотите, была созданаglOrtho
. В то время как все эти команды устарели, документы по ним являются отличным источником некоторых предварительно полученных математических данных.При вызове glViewport вы указываете меньше пикселей по ширине и высоте. Ваша матрица проекции определяется в пикселях. Вот почему вам придется вычислять новую матрицу проекции после вызова glViewport.
источник
Для первой картинки:
Мы создаем проекционную матрицу. Например, используются следующие параметры: Left1, Right1, Bottom1, Top1, Near1, Far1. Здесь Aspect_Ratio_1A = (справа1 - слева1) / (сверху1 - снизу1);
Затем мы делаем преобразование порта просмотра. Например, используются следующие параметры: Ширина1, Высота1. (Я не упоминаю параметры сдвига для простоты). Здесь Aspect_Ratio_1B = Ширина1 / Высота1;
Для второй картинки:
Мы создаем ту же матрицу проекции с теми же параметрами, что и раньше. Итак: Aspect_Ratio_2A = Aspect_Ratio_1A;
На этот раз преобразование порта просмотра имеет разные параметры: ширина2 и высота2. Здесь Aspect_Ratio_2B = Ширина2 / Высота2.
Отметим, что Aspect_Ratio_1B и Aspect_Ratio_2B различны. В частности, они являются:
Aspect_Ratio_1B = 2560/1600 = 1.6 Aspect_Ratio_2B = 2560/1200 = 2.13
Итак, если мы суммируем, что мы делаем для второго случая:
Мы проецируем изображение на плоскость с помощью Aspect_Ratio_2A и, прежде чем показать его пользователю, мы масштабируем его до Aspect_Ratio_2B. Другие пользователи просят нас исправить нашу матрицу проекции таким образом, чтобы Aspect_Ratio_2A = Aspect_Ratio_2B.
Мы также можем прочитать комментарии Роберта пару раз, чтобы лучше понять.
Кроме того, я не могу согласиться с тем, что красный квадрат на втором изображении имеет размер 200 на 200 пикселей при отображении на экране. Поскольку мы знаем, что пиксель является квадратом, если у четырехугольника одна из сторон длиннее другой, более длинная сторона наверняка потребует больше пикселей. Лично я не знаю, что такое логирование, но, возможно, оно не возвращает размер пикселя экрана.
источник