Что именно заставляет поверхность перекрывать другую?

10

Я действительно не могу понять, что заставляет одну поверхность перекрывать другую. В 3D движке, который я создаю, моя техника терпит неудачу в крайних случаях.

Мой метод сортировки поверхностей, которые будут окрашены, от самых дальних к ближайшим. Чтобы определить близость, я сравниваю средние значения z. Однако иногда перекрывающаяся поверхность имеет более высокое среднее значение z, чем та, которую она перекрывает. Таким образом, поверхность, расположенная дальше, закрашивается более близкой, что приводит к причудливому рендерингу следующим образом:

Большой фиолетовый квадрат с красным сечением сбоку

То, что нужно видеть, это фиолетовая передняя поверхность куба, а красная боковая поверхность закрашена пурпурной. Среднее значение z пурпурной поверхности выше, и поэтому «дальше». Поэтому у меня есть некоторые сомнения относительно правильности этой техники.

Я также пытался определить расстояние от камеры (то есть до начала координат) до поверхности, но затем мне понадобилась точка. Я выбрал середину каждой поверхности, но также это не всегда работает, потому что не все поверхности такие большие, как друг друга.

Следовательно, каков надежный способ определения порядка близости поверхностей к началу координат?

pimvdb
источник

Ответы:

11

Вы, кажется, пытаетесь реализовать алгоритм Painters . Я предполагаю, что вы пытаетесь написать растеризатор с нуля в качестве учебного упражнения, так как большинство современных 3D-устройств использует то, что упомянул Барт (буфер Z / Depth). Чтобы алгоритм рисования работал во всех случаях, вам необходимо быть готовым к разделению поверхностей по мере их отображения для решения возможных сценариев (например, проблема перекрывающегося многоугольника, показанная на странице Википедии).

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

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

Роджер Перкинс
источник
Вы правы, говоря, что я создаю простой рендер. Дело в том, что я не использую никаких 3D-библиотек. Я сам делаю все расчеты проекции, а затем рисую линии, используя библиотеку 2D-рисования. Это не самое быстрое, и я ничего не делаю для каждого пикселя. У меня просто есть 4 точки на каждой поверхности и я заливаю прямоугольную форму цветом. Так как я рисую всю поверхность за один раз, правильно ли я говорю, что я должен отступить назад?
pimvdb
Похоже, очень весело и отличный способ учиться. Обратный путь - ваш единственный способ, если вы делаете это без какой-либо формы буфера глубины. Я думаю, что вам нужно будет отработать все координаты экрана ваших полигонов, а затем проверить наличие совпадений. Там, где они частично совпадают, вам может понадобиться разделить полигоны для рендеринга, чтобы вы могли правильно разрешить сортировку. Возможно, вы также захотите изучить Back Face Culling как способ удаления полигонов, которые не обязательно должны быть видны
Роджер Перкинс
Роджер Перкинс прав. Вы не сможете добиться правильной z-сортировки таким образом (то есть у вас всегда будут некоторые крайние случаи), если вы не порежете полигоны. Это может стать довольно медленным, хотя.
bummzack
Я получил это работает! То, что я сделал, было комбинацией отбраковки и сортировки задней поверхности: в сплошном кубе некоторые грани не видны, а другие (максимум 3). Поэтому я сначала закрасил невидимые части, а видимые - поверх них. Это работает как брелок, если я удаляю одну или несколько сторон, они накладываются друг на друга, но все равно нарисованы в правильном порядке. Спасибо!
pimvdb
1
Это будет работать только для простых выпуклых фигур, таких как кубики. Я рад, что в настоящее время это работает для вас, но это не общее решение.
Ричард Фабиан
3

У вас есть проблема видимости . Одним из решений является использование z-буфера .

Барт ван Хейкелом
источник
Спасибо, но z-буферизация требует рендеринга за пиксель, если я не ошибаюсь. Я этого не делаю - я рисую прямые линии между проецируемыми точками куба. Возможна ли z-буферизация?
pimvdb
Даже если вы рисуете прямые линии, в какой-то момент, прежде чем изображение попадет на экран (или в растровый файл), оно будет в пиксельном формате.
Барт ван Хейкелом
Это правильно, но моя библиотека рисования слишком медленная, чтобы делать рендеринг пикселей с 20fps. Спасибо хоть.
pimvdb
2

Сортировка граней по их среднему z-значению не работает, поскольку среднее z-значение не предоставляет информации о фактическом z-значении вершин или даже пикселей поверхности.

Пример (предупреждение, ASCII искусство впереди):

          /
         /
cam     /
-->    / 
      /
     /--       <--B
    /
    ^--A

Есть две грани A и B. С точки зрения камеры A перед B. Тем не менее, среднее значение z для B меньше. Давайте посмотрим на другие z-значения:

  • минимальное значение z составляет 4
  • максимальное значение z составляет 11
  • поэтому среднее значение z составляет 7,5
  • минимальное значение z для B составляет 6
  • максимальное z-значение B равно 8
  • поэтому среднее значение z составляет 7

Вы можете попытаться отсортировать их по минимальным z-значениям, но в некоторых случаях это тоже не сработает. Просто невозможно правильно отсортировать произвольные грани, используя только одно z-значение.

В алгоритме Ньюэлла http://en.wikipedia.org/wiki/Newell 's_algorithm, что вы делаете, сортируете минимальные / максимальные диапазоны z-значений. Если диапазоны двух граней не перекрываются, вы можете точно знать, какая из них впереди. Если они это делают, иногда вам абсолютно необходимо разделить лица. Иногда достаточно будет проследить каждую вершину для окклюзии или какой-либо другой техники.

Йонас Бетел
источник
Эта диаграмма представляет собой вид сверху того, что я собирался угадать, что происходит на его скриншоте.
Джоккинг
1

Хорошо, что вы изучаете рендеринг в действии. Престижность. В этом случае на PS1 нет решения «алгоритма рисования», вместо того, чтобы пытаться исправить его путем сортировки, на котором мы просто пытались держать полигоны примерно одинакового размера, когда они были рядом друг с другом (что вы делаете как насколько я могу судить), и задняя часть отбраковки (что вы не делаете)

Отбор задней поверхности - это проверка нормали поверхности в пространстве экрана на предмет ее направления (достаточно получить знак элемента глубины из пространства экрана, преобразованного в нормаль (в нашем случае это была z нормали), или перекрестное произведение двух векторов треугольник, то есть крест (v1-v0, v2-v0))

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

Ричард Фабиан
источник
Спасибо за ваш ответ. Я читал о отбраковке задней поверхности, но дело в том, что я хотел бы иметь возможность удалить одну сторону. С твердым кубом это может работать просто замечательно, но если я уберу одну сторону, то произойдет затворничество - так что мне все равно нужно их отсортировать, я думаю. Во всяком случае, мне пришла в голову идея запустить луч из источника через середину поверхности. Если этот луч пересекает другую поверхность впоследствии, то первая поверхность перекрывает вторую. Не могли бы вы сказать мне, правильна ли эта идея? Спасибо!
pimvdb
Хотя ваша идея подойдет для вашего примера, есть много других случаев, когда она не сработает. Например, та же сцена, что и у вас, но с наклоном камеры, чтобы центр неправильного квадрата рендеринга не перекрывался. Я думаю, вам придется тесселить ваши примитивы на более мелкие кусочки.
Ричард Фабиан