Нахождение длины луча внутри куба

У меня есть луч, идущий наружу от камеры, мне нужно найти длину луча внутри куба. Обратите внимание, что камера может находиться внутри куба, и в этом случае она должна возвращать расстояние до края куба.

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

Любые идеи?


person Hannesh    schedule 22.11.2010    source источник


Ответы (2)


Чтобы пересечь луч с выпуклым многогранником, пересечь луч с плоскостями, содержащими каждую грань.

Предположим, что луч начинается в точке q и имеет направление r. Тогда любую точку на луче можно представить как q + t r для скалярного параметра t. Теперь предположим, что мы хотим пересечь этот луч с плоскостью, заданной уравнением p · n = k (где n — направленная наружу единица, нормальная к лицу). Луч пересекает плоскость, когда

(q + t r) · n = k

То есть, когда

q · n + t r · n = k

так что

t = (kq · n) / r · п

Луч входит в грань, когда r · n имеет отрицательное значение, и выходит, когда r · n является положительным. Когда r · n равно нулю, луч параллелен грани. Вам нужно проверить этот случай, чтобы избежать деления на ноль; и в этом случае, если q · n > k, луч полностью проходит мимо многогранника.

Итак, найдите t для всех граней вашего многогранника и пусть tin будет максимальным t для точек где луч входит в грань, а tout – минимальное значение t для точек, в которых луч выходит из грани. Тогда длина луча внутри многогранника равна

max(max(tвыход, 0) − max(tвход, 0), 0) / | р|

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

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

person Gareth Rees    schedule 22.11.2010
comment
Спасибо! Перевод на язык шейдеров openGL не составит труда. Поскольку мой куб выровнен по оси, я могу еще больше упростить ваши и без того компактные уравнения! Это будет отлично работать. - person Hannesh; 22.11.2010
comment
что здесь к? Похоже, что это должно быть плоское смещение, p0, но если это так, то почему это не указано? - person Krupip; 01.09.2018
comment
@opa: Вы правы в том, что |k| - это перпендикулярное расстояние плоскости от начала координат, но я предположил, что ОП был знаком с уравнением плоскости, и поэтому мне не нужно было напоминать им об этой детали. - person Gareth Rees; 01.09.2018
comment
уравнение плоскости определяется согласно википедии как (p-p0)*n = 0. Это также единственное определение самолета, которое я видел до этого. Тому, кто знаком с этим определением, оно кажется чуждым. - person Krupip; 02.09.2018
comment
@opa: Вам просто нужно раскрыть скобки: если (p − p₀)·n = 0, то p·n = p₀·n = k. - person Gareth Rees; 02.09.2018

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

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

  1. Нет пересечения
  2. Один перекресток - вы находитесь внутри куба, рассчитайте расстояние между перекрестком и положением камеры
  3. Два пересечения - вы находитесь вне куба, рассчитайте расстояние между двумя пересечениями
  4. Бесконечно много пересечений - вектор вида является касательным к кубу, просто отбросьте пересечения касательных плоскостей и возьмите только два пересечения с двумя соседними плоскостями

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

person Karel Petranek    schedule 22.11.2010
comment
Извините, я не забуду объяснить больше о том, что я делаю в будущем. Я моделирую атмосферу в форме куба, и мне нужно знать, какую часть атмосферы мы просматриваем, чтобы определить цвет. Я рассмотрю возможность использования z-буфера, так как я могу сделать реалистичный туман и для ландшафта. Также вычисление выполняется для каждой вершины. - person Hannesh; 22.11.2010
comment
Зачем использовать куб? Сфера (или полусфера) определенно больше подходит для атмосферы. Кроме того, вычисления пересечения значительно проще. - person Karel Petranek; 23.11.2010
comment
Поскольку наш мир представляет собой гигантский куб, кубический мир заслуживает не меньше кубической атмосферы. - person Hannesh; 24.11.2010