Идея реализации 3D-тени

Предположим, что ваш глаз находится в точке P1 поверхности объекта A, и есть объект-объект B и есть источник точечного света за объектом B.

Вопрос: Я прав, если я смотрю на источник света и говорю "я в тени", если я не вижу свет из-за объекта B?. Затем я отмечаю, что точка объекта A является "одной из теневых точек B на A".

enter image description here

Если это так, тогда мы можем построить на поверхности A объект "теневой геометрии" (черный цвет), а затем изменить его постоянно из-за движения света, B, A и т.д. в в реальном времени? Допустим, что сфера (A) имеет 1000 вершин, а другая сфера (B) также имеет 1000 вершин, так это означает 1 миллион сравнения? (затеняет, O (N ^ 2) (время) сложность?). Я не уверен в сложности, потому что изменение P1 (глаз) также изменяет видимую точку B (между P1 и точкой источника света). Как насчет теней второго порядка и выше (например, много света отражаются между двумя объектами)?

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

Спасибо.

Изменить: Мне нужно отключить "камеру" при перемещении камеры, чтобы создать эту тень. Как я могу это сделать? Это плохо влияет на производительность?

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

Любой, кто снабжает библиотеку реальной тени для java3d, будет очень полезен.

Очень маленькая проба Geomlib shadow/raytracing в java3D была бы лучшей Пример трассировки лучей может быть?

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

Спасибо.

Ответ 1

Ваш подход можно суммировать следующим образом:

foreach (point p to be shaded) {
    foreach (light) {
        if (light is visible from p)
            // p is lit by that light
        else
            // p is in shadow
    }
}

Забавный факт заключается в том, что в реальном времени тени на GPU выполняются.

Однако для этого нет тривиальной работы для эффективной работы. Рендеринг сцены - это упорядоченный процесс, треугольник по треугольнику. Было бы очень громоздко, если бы для каждой отдельной точки (пикселя, фрагмента) в каждом отдельном треугольнике вам нужно было рассмотреть все остальные треугольники в другом, чтобы проверить пересечение луча.

Итак, как это сделать эффективно? Ответ. Отмените процесс.

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

// preprocess
foreach (light) {
    // find all pixels p on the scene reachable from the light
}
// then render the whole scene...
foreach (point p to be shaded) {
    foreach (light) {
        // simply look up into what was calculated before...
        if (p is visible by the light)
            // p is lit
        else
            // p is in shadow
    }
 }

Это кажется намного быстрее... Но остаются две проблемы:

  • Как найти все пиксели, видимые светом?
  • как быстро сделать их доступными для поиска во время рендеринга?

Там сложная часть:

  • Чтобы найти все точки, видимые светом, поместите туда камеру и отрисуйте всю сцену! Тест глубины отклонит невидимые точки.
  • Чтобы сделать этот результат доступным позже, сохраните его как текстуру и используйте эту текстуру для поиска во время фактической стадии рендеринга.

Этот метод называется Shadow Mapping, а текстура с пикселами, видимыми из света, называется Shadow Map. Более подробное объяснение см., Например, в статье Wikipedia.

Ответ 2

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

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

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

Несколько актуальных вопросов:

Как создать дешевые тени в OpenGL?

Есть ли простой способ получить тени в OpenGL?

Каков самый простой способ рендеринга теней на сцене в OpenGL?

Ответ 3

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

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

Ответ 4

3D-рендеринг теней на ваниле Java никогда не будет эффективным. Лучше всего использовать графические библиотеки, написанные для использования полного диапазона возможностей графической карты, например OpenGL или DirectX. Когда вы используете Canvas (из приведенного вами скриншота), вы можете даже рисовать Canvas из собственного кода с помощью JNI. Таким образом, вы можете использовать всю технологию из графических библиотек, просто немного поиграть и нарисовать свой холст непосредственно из собственного кода. Было бы очень мало работы, чтобы заставить его работать, по сравнению с написанием собственного 3D-движка.

Ссылка на Wiki о собственном доступе AWT: http://en.wikipedia.org/wiki/Java_AWT_Native_Interface Документация: http://docs.oracle.com/javase/7/docs/technotes/guides/awt/AWT_Native_Interface.html