#opengl #opengl-4
#opengl #opengl-4
Вопрос:
glViewport: ширина / высота — это целые числа (которые являются пикселями).
Но glViewportIndexed имеет эти значения в float. Каковы преимущества их использования в float. Мое понимание основано на том факте, что пиксели всегда являются целыми числами.
Комментарии:
1. Ну, это не совсем так. Расположение пикселей с фиксированной точкой, возможно, в какой-то момент вы слышали термин «субпиксельная точность»… 8-битная субпиксельная точность означает, что вы действительно можете адресовать области пространства размером 1/256 пикселя. Многие вещи (например, примитивное покрытие) не будут корректно работать с 0-битной субпиксельной точностью.
2. Когда-нибудь проверьте значение
gl_FragCoord.x
в шейдере фрагмента (эти координаты находятся в пространстве окна). Обратите внимание, что он не ограничен целочисленными координатами? Вы выполняете выборку из центра фрагмента (растеризация одного образца), и по соглашению по умолчанию этот центр смещен на половину целого числа.3. @AndonM. Коулман, ок, понял. Но тогда почему glViewport имеет x, y, w, h в целых числах? Применяется ли преобразование окна просмотра ко всем окнам просмотра или только к первому окну просмотра.
4. @AndonM. Коулман, 2-й вопрос: если VIEWPORT_SUBPIXEL_BITS возвращает значение 4, то будет ли gl_FragCoord.xy иметь значения со смещениями (0,0) (0.5, 0) (0, 0.5) и (0,5, 0,5) ?
Ответ №1:
Может показаться glViewport*()
, что вызовы определяют пиксельные прямоугольники. Но если вы посмотрите на детали конвейера рендеринга OpenGL, это не так. Они определяют параметры для преобразования окна просмотра. Это преобразование, которое отображает нормализованные координаты устройства (NDC) в координаты окна.
Если x
, y
, w
и h
являются указанными вами размерами окна просмотра xNdc
и yNdc
вашими координатами NDC, преобразование окна просмотра можно записать следующим образом:
xWin = x 0.5 * (xNdc 1.0) * w;
yWin = y 0.5 * (yNdc 1.0) * h;
В этом вычислении xNdc
и yNdc
, конечно, являются значениями с плавающей запятой в их обычном (-1.0, 1.0) диапазоне. Я не вижу никаких веских причин, почему x
, y
, w
и h
должны быть ограничены целочисленными значениями в этом расчете. Это преобразование применяется перед растеризацией, поэтому нет необходимости округлять что-либо до единиц измерения в пикселях.
Отсутствие необходимости в целочисленных значениях для размеров окна просмотра может быть даже практически полезным. Допустим, у вас есть окно размером 1000×1000, и вы хотите отобразить 9 вложенных представлений одинакового размера в окне. У API нет причин мешать вам делать то, что наиболее естественно: сделать каждый подвид размером 333.3333×333.3333 и использовать эти размеры для параметров glViewport()
.
Если вы посмотрите glScissorIndexed()
для сравнения, вы заметите, что он по-прежнему принимает целочисленные координаты. Это имеет полный смысл, потому gScissor()
что на самом деле указывает область пикселей в окне, в отличие glViewport()
от .
Комментарии:
1. Итак, если я разделю 1000×1000 на 9 видовых экранов размером 333.3333×333.3333 каждый, и теперь я хочу вырезать первый видовой экран. Я указываю (333,333) в glScissorIndexed(), увижу ли я разрыв на конечном экране в зависимости от точности VIEWPORT_SUBPIXEL_BITS ?
Ответ №2:
Ответить на ваши новые вопросы в комментариях было бы сложно, поэтому, хотя Рето Коради уже ответил на ваш вопрос, я попытаюсь ответить на них здесь.
@AndonM.Коулман, ок, понял. Но тогда почему glViewport имеет x, y, w, h в целых числах?
Вероятно, потому, что при glViewport (...)
создании не было программируемого конвейера. Даже тогда иногда использовались субпиксельные смещения (особенно при попытке соответствовать правилам покрытия растеризации для таких вещей, как GL_LINES
и GL_TRIANGLES
), но они должны были применяться к матрицам преобразования.
Теперь вы можете сделать то же самое, используя вместо этого преобразование области просмотра, что намного проще (для области просмотра требуется 4 скаляра), чем передача гигантского mat4
(16 скаляров) в геометрический шейдер.
Применяется ли преобразование окна просмотра ко всем окнам просмотра или только к первому окну просмотра.
Из GL_ARB_viewport_array
спецификации расширения:
glViewport
устанавливает параметры для всех окон просмотра в одинаковые значения и эквивалентно (при условии, что ошибки не генерируются):for (GLuint i = 0; i < GL_MAX_VIEWPORTS; i ) glViewportIndexedf(i, 1, (GLfloat)x, (GLfloat)y, (GLfloat)w, (GLfloat)h);
@AndonM.Коулман, 2-й вопрос: если VIEWPORT_SUBPIXEL_BITS возвращает значение 4, то будет ли gl_FragCoord.xy иметь значения со смещениями (0,0) (0.5, 0) (0, 0.5) и (0,5, 0,5) ?
Если у вас есть 4-битная субпиксельная точность, то это означает, что позиции вершин после преобразования будут привязаны к позиции 1/16-й ширины пикселя. GL на самом деле не требует здесь каких-либо подпиксельных битов; в таком случае ваши позиции вершин после преобразования в оконное пространство будут прыгать на 1 пиксельное расстояние за раз, и вы увидите много «блесток» при перемещении чего-либо в сцене.
Эта анимация демонстрирует «блестки»; она возникла отсюда:
Видите белые точки при движении камеры? Если при преобразовании вершин у вас недостаточно субпиксельной точности, растеризатору трудно правильно обрабатывать ребра, которые должны быть смежными. Технический термин для этого — ошибка Т-образного соединения, но мне очень нравится слово «блестящий» 😉
Что касается gl_FragCoord.xy
, нет, на самом деле это не зависит от вашей субпиксельной точности во время преобразования вершин. Это примерное местоположение в вашем фрагменте (обычно выровнено по … 0,5, как вы указываете), и оно не связано с обработкой вершин.