Как мне обращаться с обтравочными вершинами, которые ближе к глазу, чем ближняя плоскость отсечения?

13

Я использую свой собственный 3D-движок на JavaScript и использую только рисование на холсте, а не WebGL. Это еще один клон Minecraft; Я люблю коробки, не суди меня.

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

Я попытался обрезать эти точки, но затем я могу видеть поверхности, которые используют эти вершины. В WebGL / OpenGL графическая карта заботится об этих точках, и плоскость отображается правильно, но у меня нет доступа к оборудованию, поэтому я должен кодировать это сам.

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

Вот мои мысли:

введите описание изображения здесь

Вот несколько изображений, чтобы проиллюстрировать, что происходит:

введите описание изображения здесь

С расстояния синяя коробка отрисовывается на отлично.

введите описание изображения здесь

Когда некоторые вершины идут за плоскостью отсечения игрока, я делаю обратную проекцию, но она выглядит неправильно:

focalLength *= -1;
2d.x = x*focalLength/z;
2d.y = y*focalLength/z;

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

введите описание изображения здесь

Вот что происходит, когда смотришь вверх или вниз.

Я не знаю, что делать с этой математикой, я надеюсь, что кто-то уже сталкивался с той же проблемой и может мне помочь.

соленоид
источник
1
Если точки ближе к глазу, чем ближняя плоскость отсечения , они должны быть обрезаны - и это действительно может позволить вам видеть «сквозь» объект. Это типичное поведение; столкновение обычно предотвращает этот конкретный визуальный артефакт. Это было единственное, что не так с вашим решением для стрижки?
@JoshPetrie: Я понимаю, что точки должны быть обрезаны, но если я это сделаю, весь квадрат исчезнет, ​​так как одна или две вершины, по которым должна пройти процедура рисования, отсутствуют (в 2d), и игрок сможет увидеть через эту площадь. Я бы хотел, чтобы они были «вне» холста (на проекции), чтобы квадрат можно было рисовать. Я не уверен, если я достаточно ясно.
Соленоид
Вы - я говорю , что это нормальное поведение , и вы хотите , чтобы предотвратить это путем предотвращения игрока от получения , что близко к одному из кубиков. Если вы действительно хотите сделать это, вы должны обрезать, но восстановить треугольники (возможно). Это все равно будет выглядеть необычно, особенно если у вас есть текстуры. Если то, что я говорю, не имеет смысла, вы можете присоединиться к нам в чате, чтобы мы не создавали очень болтливую ветку комментариев.
То, что вы говорите, имеет смысл, реконструкция занимает слишком много времени, так что это не решение проблемы. Я надеялся, что есть способ по-прежнему рисовать эту вершину на 2-й плоскости, которая находится позади игрока, так что lineTo(x,y)функция все еще может быть вызвана, только я не знаю, как она себя ведет ... это странное измерение, я согласен.
Соленоид

Ответы:

1

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

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

Проблема с вершинами, которые находятся за камерой.

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

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

Как я уже сказал: вершины в перспективной проекции, которые находятся за камерой, не имеют смысла.

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

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

Николь Болас
источник
До сих пор я отбирал весь треугольник, но потом я видел сквозь плоскость (см. Рисунки выше). Мне действительно нужна была картинка, чтобы понять, почему она не имеет геометрического смысла. Единственное решение состоит в том, чтобы вычислить пересечение плоской линии, когда одна из вершин находится позади плоскости отсечения, и использовать это пересечение, чтобы проследить линию от вершины, которая находится впереди, к сожалению, это дорого.
Соленоид
0

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

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

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

Кроме того, вот ссылка, которая может вам помочь: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter42.html

Ник Фостер
источник
Тестирование на пиксель чрезвычайно дорого в интерпретируемом языке, таком как Javascript, сейчас я получаю едва приемлемый fps как есть.
Соленоид