Какой интервал при растеризации примитивов

Обычно в информатике, когда у меня есть что-то от a до b, интервал равен [a, b). Верно ли это при растеризации геометрических примитивов?

Например, если у меня есть линия, которая начинается в позиции (0, 0) и заканчивается в позиции (0, 10), будет ли линия содержать точку (0, 10) при использовании параллельного проецирования с 1 блоком графического процессора, отображаемым на 1 пиксель на экране?

РЕДАКТИРОВАТЬ: тот же вопрос в тех же условиях, но для текстур:

Если у меня есть текстура 2x2, наложенная на четырехугольник от (0, 0) до (2, 2) с использованием сопоставления (0, 0) до (1, 1), будет ли она "идеальной по пикселям", один пиксель из текстуры на один пиксель на экране, или текстура будет масштабирована? Если интервал [0, 2], квадрат будет 3x3 и текстуру придется масштабировать...

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ: Это может помочь: http://msdn.microsoft.com/en-us/library/windows/desktop/bb219690%28v=vs.85%29.aspx


person Mircea Ispas    schedule 15.05.2013    source источник
comment
Что ты пытаешься сделать?   -  person Ani    schedule 15.05.2013


Ответы (1)


Прежде всего, это полностью зависит от конкретной используемой среды растеризации (например, OpenGL, Direct3D, GDI, ...), поэтому я буду основывать этот ответ на вопросе, отмеченном opengl.

Это не такой простой вопрос, потому что обычно фактические оконные координаты нарисованного примитива (точнее, его фрагмента) являются не целыми, а координатами с плавающей запятой или с фиксированной запятой, полученными после кучи (возможно, неточных) преобразований (которые не все можно настроить для идентификации с помощью шейдеров, особенно преобразования области просмотра с фиксированной функцией из нормализованных координат устройства в координаты окна). Таким образом, даже если вы настроите свой конвейер преобразования для указания координат вершин непосредственно в пространстве окна, не ожидайте, что оконные координаты ваших результирующих фрагментов будут идеальными целыми числами во всех случаях. Взгляните на этот вопрос и ответы на него, чтобы получить дополнительные сведения о конвейере преобразования OpenGL, если это необходимо.

Тогда это зависит от примитивного типа. Для полигона (треугольника/квадрата) растеризатор проверяет для каждого фрагмента, находится ли центр фрагмента в пределах границ полигона, как определено координатами окна вершин полигона. Итак, если у нас есть прямоугольник (ну, два треугольника, но давайте просто примем его за прямоугольник), который простирается от оконных координат (0,0) до (2,2), он покроет область 2x2, потому что только фрагменты (0,0) (с центральной координатой (0.5,0.5)) и (1,1) (с координатой центра (0.5,0.5)) координата центра (1.5,1.5)), и их комбинации лежат внутри прямоугольника.

Для строк это немного сложнее, используя так называемый "алмазное правило выхода". Я не буду подробно обсуждать это здесь, но для горизонтальных или вертикальных линий это, по сути, означает, что последний пиксель также является эксклюзивным. Но на самом деле это также означает, что целочисленные координаты окна хуже всего использовать для линий, потому что из-за проблем с округлением в конвейере преобразования трудно решить, какому пикселю принадлежит такой фрагмент, поскольку «порог принятия решения» для линий равен границы целочисленного фрагмента, а не его центр, как для полигонов.

Но при текстурировании возникает другая проблема, а именно интерполяция. В то время как четырехугольник от (0,0) до (2,2) покрывает область размером 2x2 пикселя, значения вариаций (атрибуты вершин, интерполированные по примитиву, такие как координаты цвета или текстуры) интерполируются из фактических координат окна. Таким образом, пиксель (0,0) (соответствующий фрагменту с центральной координатой (0.5,0.5)) будет иметь не точные значения нижней левой вершины четырехугольника, а значения, интерполированные внутрь на половину размера фрагмента (и аналогично для других углов) .

Что также имеет значение, так это то, как OpenGL фильтрует текстуры. При использовании линейной фильтрации точный цвет текселя возвращается для координат текстуры в центрах текселей (например, (i+0.5)/size), а целые делители размера текстуры (например, i/size) приводят к полутоновому смешению между соседними цветами текселей. И при использовании выборки ближайшего соседа вместо этого (что рекомендуется при попытке сделать что-то с точностью до пикселя или текселя) координата текстуры с плавающей запятой округляется в меньшую сторону (фундаментальная операция) и, таким образом, «порог решения», который решает, является ли цвет от одного тексела или его соседа находится на границах текселя (таким образом, целые делители размера текстуры как координаты текстуры). Так что выборка в центрах текселей целесообразна как при линейной фильтрации (что, в свою очередь, нецелесообразно при работе с точностью до пикселя), так и при ближайшей фильтрации, так как это снижает вероятность «перелистывания» с одного текселя на другой из-за неточностей и ошибок округления в интерполяция текстурных координат.


Итак, давайте посмотрим на ваш конкретный пример. мы получили квадроцикл с координатами

(0,2) - (2,2)
  |       |
(0,0) - (2,0)

и текстурные координаты

(0,1) - (1,1)
  |       |
(0,0) - (1,0)

Поэтому, если эти позиции уже заданы в пространстве окна/просмотра, это приводит к фрагментам с центрами

(0.5,1.5) (1.5,1.5)
(0.5,0.5) (1.5,0.5)

покрытый, представляющий квадрат 2x2-[0,1] пикселя. Текстурные координаты этих фрагментов после интерполяции будут

(0.25,0.75) (0.75,0.75)
(0.25,0.25) (0.75,0.25)

И для текстуры 2x2 они действительно находятся в центрах текселей. Так что все прекрасно играет. Могут быть ошибки округления и точности, приводящие, например, к. координаты 1.999 или texCoords 0.255, но это все равно не проблема, так как мы далеки от точек, где можно было бы "привязаться" к соседним пикселям или текселям (при условии, что мы используем ближайшую фильтрацию, но даже при линейной фильтрации вы обычно не заметит разницы с точным цветом текселя).

Хотя для примера строки трудно сказать, из-за проблем с точностью, округлением и реализацией, будет ли это от (0,0) до (0,9) или от (-1,0) до (-1,9) (таким образом, обрезано), или даже с перекосом, и вам лучше использовать (0.5,0.5) и (0.5,10.5), что обязательно приведет к строке от (0,0) до (0,9).


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

glViewport(0, 0, width, height);
glOrtho(0, width, 0, height, -1, 1); //or something similar when using shaders

Затем для полигонов используйте целые позиции и целые делители размера текстуры в качестве координат текстуры (и используйте фильтрацию GL_NEAREST). Но для линий используйте полупиксельные позиции (например, i+0.5) и центры текселей в качестве координат текстуры (например, (i+0.5)/size). Это должно дать вам точную растеризацию ваших примитивов и полуоткрытых интервалов, описанных в вашем вопросе, с точностью до пикселя и текселя. Но всегда имейте в виду, что в этом случае конические пиксели растеризованного полигона не совпадают с его вершинными углами (сдвинуты внутрь на полпикселя). Для текстурирования это прекрасно работает с правилами фильтрации, но для других атрибутов, таких как цвета, это означает, что нижний левый пиксель прямоугольника не будет точно (что означает "точно" в этом ограниченном- в любом случае контекст точности?) цвет нижней левой вершины. Однако для строк они действительно будут совпадать (насколько это возможно).

person Christian Rau    schedule 15.05.2013