Скалярное произведение в разработке игр: проекции и прыгающие мячики в Unity ⛹
furry.cat
Скалярное произведение – простой, но чрезвычайно полезный математический инструмент. Он кодирует отношение между величинами и направлениями двух векторов в единственное скалярное значение. Его можно использовать для вычисления проекции, отражения, расчета тени и постановки освещения. Из этого руководства вы узнаете:
- Геометрический смысл скалярного произведения.
- Как спроецировать один вектор на другой.
- Как измерить размер объекта вдоль произвольной оси.
- Как отразить вектор относительно плоскости.
- Как создать эффект отскока мяча от наклонной поверхности.
Скалярное произведение
Представьте два вектора a и b . Вектор характеризуется только направлением и величиной (длиной), поэтому не имеет значения, в каком месте плоскости он расположен. Допустим, оба вектора начинаются в одной точке:
a и b , выходящие из одной точки плоскости” data-src=”https://media.proglib.io/posts/2020/04/04/182e211c01704ab48d14f469d9838df4.png” > Два вектора a и b , выходящие из одной точки плоскости
Проекцию одного вектора на другой можно представить как отбрасывание тени от первого вектора в направлении, перпендикулярном второму:
Проекция одного вектора на другой
Как вы знаете, операция вычисления произведения векторов записывается так:
Далее в статье мы будем использоваться запись a * b .
Если между векторами острый угол, то длина проекции будет положительной величиной, если больше – то отрицательной.
Если b – единичный вектор, то величина проекции a на b – это просто произведение a * b .
Вычисление скалярного произведения через косинус угла
На схеме изображен прямоугольный треугольник. Угол между векторами a и b равен θ .
Два вектора образуют прямоугольный треугольник
Для начала требуется рассчитать величину проекции вектора a на вектор b – это нижний катет в нарисованном нами треугольнике. Длину катета стороны можно найти, умножив длину гипотенузы треугольника на косинус прилежащего угла.
a на вектор b – это катет прямоугольного треугольника” data-src=”https://media.proglib.io/posts/2020/04/04/c4a332573e7bdc88dcc72dddf457044d.png” > Проекция вектора a на вектор b – это катет прямоугольного треугольника
Итак, длина проекции равна произведению модуля вектора a на косинус угла θ . Скалярное произведение можно выразить следующим образом:
Формула вычисления скалярного произведения через косинус
Эта формула лишний раз подтверждает, что порядок умножения не важен – в результат входят беззнаковые длины обоих векторов. Если оба вектора – единичные, правая часть формулы упрощается до cos(θ) . А если угол равен 90° (векторы перпендикулярны), то их произведение равно 0 .
Если угол острый (меньше 90°), результат будет положительным, так как косинус такого угла больше 0. Аналогично для тупого угла получится отрицательный результат. Таким образом, знак скалярного произведения дает нам некоторое представление о направлениях векторов.
Функция косинуса монотонно убывает на промежутке от 0 до 180° (от 1 до -1 ). Следовательно, чем ближе направления двух векторов, тем больше их скалярное произведение и наоборот.
- Направления совпадают, угол θ равен 0°, произведение равно |a| * |b| .
- Направления противоположны, угол θ равен 180°, произведение – -1* |a| * |b| .
Вычисление скалярного произведения через компоненты векторов
Если наши векторы расположены в 3D-пространстве и имеют по три координаты каждый, не совсем понятно, где тот угол, косинус которого нужно вычислить. К счастью, существует другой способ расчета скалярного произведения – без всякой тригонометрии! Для начала нужно разложить каждый вектор на компоненты:
Разложение векторов на компоненты
Намного проще и без всяких косинусов! В Unity есть встроенный метод Vector3.Dot для вычисления скалярного произведения двух векторов:
Его реализация выглядит следующим образом:
Нам известно, как найти длину вектора по его координатам:
Но ее можно выразить и через скалярное произведение вектора на себя:
Вернемся к формуле a * b = |a| * |b| * cos θ . При известных длинах векторов мы можем вычислить угол между ними с помощью функции арккосинуса:
Вычисление величины угла между векторами
Если оба вектора являются единичными, мы можем упростить формулы:
Упрощенные формулы для единичных векторов
Проекция вектора
Теперь, когда нам известно геометрическое значение скалярного произведения векторов (произведение длины со знаком первого проецируемого вектора и длины второго вектора), мы можем перейти к практическому применению этого знания. Например, спроецируем один вектор на другой.
Пусть вектор с = project ba – это проекция вектора a на вектор b .
Вектор c – проекция вектора a на вектор b
Возьмем единичный вектор в направлении вектора b . Он будет равен b / |b| . Если мы возьмем величину проекции a на b со знаком и умножим на этот единичный вектор, то получим вектор c . Cкалярное произведение a * b – это результат умножения длины b на длину проекции a на b . Отсюда получаем, что длину c со знаком можно найти, разделив скалярное произведение a * b на длину b :
Вычисление длины проекции одного вектора на другой
Умножив полученное значение на единичный вектор b / |b| , получаем формулу для нахождения проекции вектора:
Вычисление проекции одного вектора на другой
Вспомним теперь, что квадрат длины вектора равен его скалярному произведению на самого себя, и перепишем формулу:
Вычисление проекции одного вектора на другой
Если b – единичный вектор, то можно упростить еще больше:
Вычисление проекции вектора на единичный вектор
В Unity для вычисления проекции одного вектора на другой есть специальная функция Vector3.Project :
Вот так выглядит ее реализация:
Следует остерегаться возможного вырожденного случая, когда вектор, на который происходит проекция, – нулевой или имеет малую величину. При этом произойдет численный «взрыв» из-за деления на 0 или близкое к нему значение. Один из способов решить проблему – заранее вычислять величину вектора и при необходимости использовать резервный вариант (единичный вектор).
Упраженение #1. Линейка
В качестве упражнения для закрепления знаний о векторной проекции сделаем линейку, которая измеряет размер объекта вдоль произвольной оси.
Линейка характеризуется базовой позицией (точка) и осью (единичный вектор):
Как спроецировать какую-либо точку ( Point ) на линейку? Прежде всего, найдем относительный вектор от базовой позиции линейки ( Base ) до этой точки. Затем спроецируем его на ось линейки ( Axis ). Проекция точки ( Projection ) – это базовое положение линейки, смещенное на проекцию относительного вектора.
Проекция точки на линейку
Промежуточное значение relativeDot в коде отражает, насколько далеко проекция точки находится от базового положения линейки – в направлении оси линейки, если она положительная, или в противоположном направлении, если отрицательная.
Чтобы найти размер объекта вдоль оси линейки, нужно провести такие измерения для каждой вершины меша (Mesh) и найти минимальное и максимальное значение. Ответ будет равен разнице между ними.
Отражение вектора
Еще одно практическое применение скалярного произведения – отражение вектора относительно плоскости. Рассмотрим вектор v и плоскость с нормальным вектором (перпендикуляром) n .
Отражение вектора v от плоскости
Мы можем разложить отражаемый вектор на параллельную и перпендикулярную к плоскости составляющие:
Разложение отражаемого вектора на составляющие
Сам вектор является суммой параллельной и перпендикулярной составляющих:
Разложение отражаемого вектора на составляющие
Перпендикулярный компонент, как вы уже догадались – это проекция вектор на нормаль плоскости. Параллельный компонент можно получить вычитанием этой проекции из самого вектора:
Получение параллельного плоскости компонента вектора
Теперь, чтобы получить искомый отраженный вектор, нужно перевернуть перпендикулярную составляющую и прибавить ее к параллельной:
Получение отраженного от плоскости вектора
Параллельный компонент можно заменить разностью самого вектора и перпендикулярной составляющей, тогда получим следующий вид формулы:
То есть разность самого вектора и его удвоенной проекции на нормаль плоскости.
В Unity, конечно же, есть встроенная функция для расчета отраженного вектора – Vector3.Reflect :
Так выглядит реализация согласно первой выведенной нами формуле:
Упражнение #2. Отскок мяча от наклонной плоскости
Теперь, когда мы знаем все об отражении вектора от плоскости, можно переходить на следующий уровень сложности. Попробуем сымитировать движение мяча, отскакивающего от склона.
Для моделирования траектории движения шара под действием силы тяжести мы будем использовать метод Эйлера.
Чтобы определить, когда мяч ударяется о склон, нужно как-то определить момент, когда мяч проникает в плоскость.
Сфера может быть определена центром ( C ) и радиусом ( R ). Плоскость определяется нормальным вектором ( n ) и точкой на плоскости ( P ). Вектор от P до С обозначим u .
Сфера и плоскость
Если сфера НЕ проникает в плоскость, перпендикулярный плоскости компонент вектора u , должен иметь то же направление, что и вектор n , а также длину не менее R .
Перпендикулярный плоскости компонент вектора
Другими словами, сфера не проникает в плоскость, если скалярное произведение векторов u и n больше R . В противном случае величина проникновения составляет R – u * n , и положение сферы нужно исправить.
Чтобы это сделать, можно просто переместить сферу в направлении нормали плоскости n на величину проникновения. Это лишь приближенное решение, которое не является физически правильным, но для упражнения оно хорошо подходит.
Добавим логику для коррекции позиции:
Нам также нужно отразить скорость, с которой движется сфера, относительно наклона, чтобы она правильно отскакивала.
Эта анимация демонстрирует идеальное отражение и выглядит неестественной. Мы ожидаем, что с каждым отскоком скорость мяча будет уменьшаться.
Это поведение обычно моделируется значением реституции (восстановления) между двумя сталкивающимися объектами. При 100% реституции мяч идеально отскакивает от плоскости. При 50% – величина перпендикулярной к плоскости составляющей скорости мяча будет уменьшена вдвое.
Величина реституции – это отношение величин перпендикулярного к плоскости компонента скорости мяча до и после отскока.
Вот пересмотренный с учетом коэффициента восстановления скорости вариант функции отражения:
Вот так выглядит обновленная функция SphereVsPlane :
Логика корректировки позиции заменяется логикой полноценного отскока:
Теперь мы можем устанавливать разные коэффициенты реституции для разных шариков:
Заключение
Мы ответили на все вопросы, заданные в начале этого руководства.
- Скалярное произведение двух векторов – это произведение проекции первого вектора на второй (с учетом знака) и модуля второго вектора.
- Существует две формулы вычисления скалярного произведения: через косинус угла и через компоненты векторов.
- Скалярное произведение имеет множество полезных практических применений. Например, оно позволяет рассчитать проекцию вектора на другой вектор.
- С помощью скалярного произведения можно найти отраженный от плоскости вектор. На этой основе строятся различные физические модели, например, имитация отскока шарика от плоскости.
Расскажите в комментариях – разрабатываете ли вы сейчас какую-нибудь игру и если да, то о чем она. Каких уроков по Unity вам не хватает?
Вычисление нормалей и углов отражения
Тема9. Построение реалистических изображений
В этом разделе мы рассмотрим методы, которые позволяют получить более-менее реалистичные изображения для объектов, моделируемых многогранниками и полигональными сетками.
Модели отражения света
Рассмотрим, как можно определить цвет пикселов изображения поверхности согласно интенсивности отраженного света при учете взаимного расположения поверхности, источника света и наблюдателя.
Зеркальное отражение света.Угол между нормалью и падающим лучом (Θ) равен углу между нормалью и отраженным лучом. Падающий луч, отраженный, и нормаль располагаются в одной плоскости (рис. 4.29).
Поверхность считается идеально зеркальной, если на ней отсутствуют какие либо неровности, шероховатости. Собственный цвет у такой поверхности не наблюдается. Световая энергия падающего луча отражается только по линии отраженного луча. Какое-либо рассеяние в стороны от этой линии отсутствует. В природе, вероятно, нет идеально гладких поверхностей, поэтому полагают, что если глубина шероховатостей существенно меньше длины волны излучения, то рассеивания не наблюдается. Для видимого спектра можно принять, что глубина шероховатостей поверхности зеркала должна быть существенно меньше 0.5 мкм
Если поверхность зеркала отполирована неидеально, то наблюдается зависимость интенсивности отраженного света от длины волны — чем больше длина волны, тем лучше отражение. Например, красные лучи отражаются сильнее, чем синие.
При наличии шероховатостей имеется зависимость интенсивности отраженного света от угла падения. Отражение света максимально для углов, близких к 90 градусам.
Падающий луч, попадая на слегка шероховатую поверхность реального зеркала, порождает не один отраженный луч, а несколько лучей, рассеиваемые по различным направлениям. Зона рассеивания зависит от качества полировки и может быть описана некоторым законом распределения. Как правило, форма зоны рассеивания симметрична относительно линии идеального зеркально отраженного луча. К числу простейших, но достаточно часто используемых, относится эмпирическая модель распределения Фонга, согласно которой интенсивность зеркально отраженного излучения пропорциональна (cosа) p , где а— угол отклонения от линии идеально отраженного луча. Показатель р находится в диапазоне от 1 до 200 и зависит от качества полировки. Запишем это таким образом:
где I— интенсивность излучения источника, Ks— коэффициент пропорциональности, который изменяется от 0 до 1.
Диффузное отражение.Этот вид отражения присущ матовым поверхностям. Матовой можно считать такую поверхность, размер шероховатостей которой уже настолько велик, что падающий луч рассеивается равномерно во все стороны. Такой тип отражения характерен, например, для гипса, песка бумаги. Диффузное отражение описывается законом Ламберта, согласно которому интенсивность отраженного света пропорциональна косинусу угла между направлением на точечный источник света и нормалью к поверхности (рис. 4.30).
где I— интенсивность источника света, Kd— коэффициент, который учитывает свойства материала поверхности. Значение Kd находится в диапазоне от 0 до 1 . Интенсивность отраженного света не зависит от расположения наблюдателя.
Матовая поверхность имеет свой цвет. Наблюдаемый цвет матовой поверхности определяется комбинацией собственного цвета поверхности и цвета излучения источника света.
При создании реалистичных изображений следует учитывать то, что в природе, вероятно, не существует идеально зеркальных или полностью матовых поверхностей. При изображении объектов средствами компьютерной графики обычно моделируют сочетание зеркальности и диффузного рассеивания в пропорции, характерной для конкретного материала. В этом случае модель отражения записывают в виде суммы диффузной и зеркальной компонент:
где константы Kd, KS определяют отражательные свойства материала.
Согласно этой формуле интенсивность отраженного света равна нулю для некоторых углов Θ и а. Однако в реальных сценах обычно нет полностью затемненных объектов, следует учитывать фоновую подсветку, освещение рассеянным светом, отраженным от других объектов. В таком случае интенсивность может быть эмпирически выражена следующей формулой:
где Iа — интенсивность рассеянного света, Ка — константа, изменяется от 0 до 1.
Можно еще усовершенствовать модель отражения, если учесть то, что энергия от точечного источника света уменьшается пропорционально квадрату расстояния. Использование такого правила вызывает сложности, поэтому на практике часто реализуют модель, выражаемую эмпирической формулой:
где R — расстояние от центра проекции до поверхности, k — константа.
Как определить цвет закрашивания точек объектов в соответствии с данной моделью? Наиболее просто выполняется расчет в градациях серого цвет (например, для белого источника света и серых объектов). В данном случае интенсивность отраженного света соответствует яркости. Сложнее обстоит дело с цветными источниками света, освещающими цветные поверхности. Например, для модели RGB составляются три формулы расчета интенсивности отраженного света для различных цветовых компонент. Коэффициент! Ка и Kd различны для разных компонент — они выражают собственный цвет поверхности. Поскольку цвет отраженного зеркального луча равен цвету источника, то коэффициент Ks будет одинаковым для всех компонент цветовой модели. Цвет источника света выражается значениями интенсивности I для соответствующих цветовых компонент.
Алгебра векторов
Здесь уместно сделать небольшое отступление от темы. Рассмотрим элементы алгебры векторов. Вектором называется отрезок прямой, соединяющий некоторые точки пространства А и В. Направление вектора — от начальной точки А к конечной точке В. Радиус-вектор R — это вектор, с начальной точкой в центре координат. Координатами радиус-вектора являются координаты конечной точки (рис. 4.31). Длина радиус-вектора часто называется модулем, обозначается как R|и вычисляется следующим образом:
Единичный вектор — это вектор, длина которого равна единице. Перечислим основные операции над векторами.
1. Умножение вектора на число X = Va. Результат — вектор X, длина которого в а раз больше вектора V. Если число а положительно, то направление вектора X совпадает с вектором V. При а
Как найти вектор отражения луча от плоскости?
У меня есть вектор, который падает на плоскость. Я знаю, что она точно падает на самолет, и я знаю точку падения. Мне нужно найти вектор отражения.
Плоскость изображена на нем тремя точками.
Что я делаю неправильно?
Вот такая логика (должна быть):
получить нормаль к плоскости ; получить проекцию направления на нормальный удвоить полученный вектор вычесть полученное из исходного вектора dir.
[spoiler title=”источники:”]
http://poisk-ru.ru/s19716t20.html
http://progi.pro/kak-nayti-vektor-otrazheniya-lucha-ot-ploskosti-3916115
[/spoiler]
Когда не нужна тригонометрия
Время на прочтение
4 мин
Количество просмотров 51K
Просматривая различный код по выводу на экран какой-нибудь даже примитивной графики, я заметил чрезмерную любовь некоторых программистов к тригонометрии. Часто код пестрит синусами, косинусами и арктангенсами там, где без них можно обойтись. Этим грешат даже хорошие программисты, которые способны спроектировать сложную систему, но почему-то не освоили вектора в объёме школьной программы. Буквально азов векторной алгебры хватает для решения многих насущных проблем. В этом топике я хочу провести краткий ликбез, напомнить основные действия с векторами на плоскости и в качестве примера решить две задачи без тригонометрии: поиск отражённого луча по падающему лучу и произвольно расположенному зеркалу, а также рисование наконечника стрелки. Если вы можете представить в голове рисование произвольно направленной стрелки без синусов и косинусов, смело пропускайте этот топик. Для остальных постараюсь объяснять попроще.
Теория
Итак, вектором (рассматриваем только двумерный случай) называется пара чисел:
Геометрический смысл — это отрезок на плоскости, для которого важна длина и направление, но не важно положение. То есть параллельный перенос не меняет вектора. Часто полезно отождествлять вектор с точкой (x,y) на плоскости — это всё равно что провести вектор из точки (0,0) в точку (x,y). Рассмотрим основные операции.
Сложение векторов:
Геометрический смысл изображён на картинке — мы перемещаем второй вектор, чтобы его начало совпало с концом первого, и результатом считаем вектор от начала первого до конца второго:
Умножение вектора на скаляр (число):
Геометрический смысл — удлинение вектора в соответствующее число раз, не меняя направление (разве что на противоположное, если a отрицательно). Умножение на -1 перевернёт вектор на 180°, не меняя длину. Деление вектора на число a — это умножение на 1/a.
Скалярное произведение векторов:
Очень важная штука. Перемножая два вектора, мы получаем число, которое характеризует длину проекции одного на другой. Перемножив два вектора, по знаку мы можем определить, направлены ли вектора в одну сторону (скалярное произведение положительно), направлены противоположно (скалярное произведение отрицательно) или перпендикулярны друг другу (произведение равно нулю). Не нужно для этого вычислять арктангенсы отношений координат каждого вектора и сравнивать углы. Два умножения, одно сложение и дело в шляпе.
Также важно, что скалярное произведение вектора самого на себя — это квадрат его длины (следствие теоремы Пифагора):
Вектор называют нормированным или единичным, если его длина равна единице. Нормировать произвольный ненулевой вектор — это поделить его на длину. Получится единичный вектор, сонаправленный исходному.
Скалярное произведение произвольного вектора на единичный даст точную длину проекции этого вектора на направление единичного. Чтобы получить не просто длину, а сам вектор-проекцию, надо умножить эту длину на наш единичный вектор:
В скобках скалярное произведение векторов a и e, а затем умножение вектора e на скаляр.
Что делать, если нам нужна проекция на ненормированный вектор? Чтобы нормировать, надо извлечь корень, а это долго и грустно. Однако, если мы приглядимся к формуле, то поймём, что нам нужно поделить результат на квадрат длины, то есть просто на скалярное произведение вектора на себя. То есть проекция a на произвольный ненулевой b будет вычисляться так:
Скалярное произведение двух единичных векторов — это косинус угла между ними. Если вдруг вам всё-таки потребовался угол между направлениями, проверьте, может, вам вовсе не угол нужен, а его косинус (или синус, который в ряде случаев можно получить из основного тригонометрического тождества). Тогда вам не потребуется ковыряться с арктангенсами.
Вот, собственно, вся базовая теория. Теперь попробуем её применить.
Вычисление отражённого луча
Отражённый луч может пригодиться не только для оптических задач, а ещё, скажем, при моделировании упругого столкновения объекта со стенкой, что незаменимо при программировании анимированных красивостей. Тогда вектор скорости объекта изменится как раз по закону отражения. Итак, у нас есть падающий вектор l и некоторая произвольная прямая, от которой производится отражение. Прямая может быть задана, к примеру, двумя точками. Требуется определить отражённый вектор r той же длины, что и l:
Зная, что угол падения равен углу отражения, можно придумать какой-то такой наивный алгоритм:
- Посчитать разность координат точек прямой, взять арктангенс их отношения — получим наклон прямой к оси x.
- Аналогично определить наклон падающего луча к оси x.
- Посчитать разность этих углов, вычесть её из 90° — получим угол падения.
- Добавить угол падения дважды и ещё 180° к углу наклона падающего луча — получим угол наклона отражённого луча.
- Вычислить длину падающего луча и умножить на синус и косинус угла наклона отражённого луча — получим результирующий вектор.
Итого: два арктангенса, синус, косинус и квадратный корень.
Однако если мыслить векторами, то простое геометрическое построение даёт существенно более быстрое решение:
Две проекции вектора l на нормаль со знаком минус да плюс ещё один вектор l в точности дадут нам результат:
Делить не надо, если нормаль уже нормирована. Кстати, я не рассказал, как её определить. Если прямая задана двумя точками (x1,y1) и (x2,y2), то вектор нормали (ненормированый) легко определяется вот так:
Иногда важен знак нормали, чтобы знать, какая сторона прямой «внешняя». В нашей задаче это неважно, вы в этом легко можете убедиться.
Кстати, полученная формула отражённого луча действует и в трёхмерном варианте, только нормаль надо определять уже для плоскости.
Рисование стрелки
Пусть заданы концы стрелки (x1,y1) и (x2,y2). Надо нарисовать усики фиксированного размера на конце (x2,y2). Посмотрим рисунок:
Здесь точка (x2,y2) обозначена буквой P. Необходимо вычислить координаты точек A и B, чтобы провести отрезки PA и PB. Будем считать, что нам задана продольная и поперечная длины усиков h и w. Внимательный читатель уже может сам предложить алгоритм: чтобы найти точку O, надо вычесть из P h, умноженное на единичный вектор вдоль стрелки (тут, похоже, без корня не обойтись, но он нужен всего один раз!). А затем A и B уже определяются, добавляя к O вектор нормали, домноженный на w и −w. Заметьте, что мы нигде не определяли угол раствора стрелки (вообще это арктангенс отношения w и h), но он нам и не нужен: стрелка легко рисуется и так.
Заключение
В целом тригонометрия пригождается не так часто. Без тригонометрических функций вычисляется преломлённый луч по закону Снеллиуса. Если вам нужно повернуть сложный чертёж на определённый угол, вам потребуется только синус и косинус этого самого угла. Из них составляется матрица вращения, и на неё домножаются по очереди все точки. Тригонометрия на самом деле медленная, особенно когда её много. Поэтому не используйте её там, где она не нужна.
В этой статье давайте поговорим о базовом расчете отражения света. Друзья, прочитавшие статью о точечном перекрестном продукте, наверняка заметили, что есть предложение ниже: «Для будущего отражения отражения света вычисление «Здесь, давайте не будем двигаться дальше, а двигаться сейчас.
Отражение света является очень важной концепцией или здравым смыслом, здесь мы говорим о реальном мире.
В реальном мире причина, по которой наши глаза видят различные объекты, заключается в том, что свет от солнца светит на землю, а затем отражается от человеческого глаза, который получает фотоны и формирует изображение на сетчатке. Затем с помощью биологических сигналов в мозг, чтобы люди видели мир.
Здесь мы называем солнце “источником света”. На самом деле, у нас также есть много искусственных “источников света”, таких как электрические лампы и лазеры. Например, в темной комнате мы включаем единственный электрический свет в комнате, и комната мгновенно освещается, и наши глаза могут видеть объекты в комнате.
ps: Здесь мы думаем о явлении: мы стоим на детской площадке в полдень и оглядываемся вокруг, мы обнаруживаем, что наши глаза могут видеть все углы детской площадки, создавая впечатление, что детская площадкаво всех направленияхЯркость такая же.
Но в темной комнате, даже если мы включим свет и оглянемся вокруг, мы обнаружим, что в комнате есть свет и тьма, и чем ближе свет, тем ярче, тем светлее и тем дальше.
Почему это явление?
Поскольку Солнце – это сначала сверхсветящая звезда с интенсивным ядерным синтезом внутри, и интенсивный свет, который он излучает, занимает восемь минут, чтобы достичь Земли. Видно, что это очень отдаленное расстояние. В этом масштабе Солнце Свет бесконечно близок к параллельному «излучению» через половину земной поверхности.
Лампа в темной комнате излучает свет от “маленького пятна” во всех направлениях. Из-за своей малой мощности и низкой интенсивности света, она не слишком яркая, когда находится немного вдали от света.
В графике определены эти два «источника света»: первый – параллельный, а второй – точечный. Здесь мы просто общаемся случайно, давайте иметь интуитивное воображение.
Затем мы входим в подразделение, чтобы объяснить,Накапливать меньшеВсе мы знаем, что даже если он такой же большой, как солнце, или такой же маленький, как электрический свет, их “осветительный” эффект достигается путем испускания “одного за другим” или даже “многочисленных” лучей света.
PS: Физически свет – это дуальность волны-частицы, а не «один», но с точки зрения графики, мы думаем, что свет – это «один»
Здесь мы обсуждаем только поведение «одного» света.
Отражение света на объекте также делится на зеркальное отражение и диффузное отражение.Метафора создания изображения состоит в том, что свет попадает на более гладкую поверхность, а отражение – зеркальное отражение, такое как зеркало. Грязное отражение (или рассеяние) света, падающего на относительно шероховатую поверхность, называется диффузным отражением, например земным, на самом деле эти два отражения имеют практически одинаковую точку, которая должна следовать закону отражения света.
Физики открыли закон отражения света, наблюдая природные явления: если луч света входит в «идеальное зеркало» с одного конца, а отраженный свет выходит с другого конца, падающий свет и отраженный свет будут разделены в «точке падения» следующим образом: Обе стороны вектора нормали N «идеального зеркала» в начальной точке и углы между падающим светом и отраженным светом равны вектору нормали N, и друзья могут представить себе отскок игры в бильярд и белых шаров, ударяющихся о край стола.
Фактически, причина, по которой диффузное отражение является «рассеянным», заключается в плоскости диффузного отражения.Бугристый», но« один »свет сияет на« грубой плоскости », фактически плоскости, где точка, в которой он отражается, также является очень« крошечным идеальным зеркалом ».
Это приводит к основной проблеме этой статьи, как рассчитать вектор отражения.
Предположим, у нас есть светящееся солнце с «идеальным зеркалом», как показано ниже:
В настоящее время мы абстрагируемся в математический график для расчета отраженного света, как показано ниже:
Как видно из этого рисунка, мы рассчитываем OB отраженного света, затем он преобразуется для вычисления OP, где OP – проекция АО на вектор нормали N, затем мы вычисляем вектор проекции, как показано ниже:
Мы вычисляем cosθ в соответствии с произведением точки, и затем мы можем получить формулу проекции вектора по OA ‘= | OA | * cosθ * единичному нормальному вектору n.
В этот раз мы возвращаемся, чтобы получить результат OB = AO + 2OP, как показано ниже:
С начала следующего: мы нашли OB = AO-2 (AO · N) · N (ps: скалярное произведение первого AO · N вычисляет скаляр m и умножает его на N, чтобы не вызвать недоразумений, вот подсказка ).
Здесь вектор АО равен вектору от точки падения до источника света, а N – единичный вектор нормали плоскости.
Эти две величины должны быть легко найдены: AO – координата точки падения и координата источника света, а N – вектор нормали плоскости (ранее полученный из перекрестного произведения), а затем унифицированный.
Говоря о том, что в основном доступны концепции и деривация формул. Далее, давайте напишем программу моделирования, чтобы увидеть эффект, как показано ниже:
Выше мы визуально моделируем путь отражения света.
Демо-адрес загрузки:https://download.csdn.net/download/yinhun2012/10273595
Для модели освещения чрезвычайно важно
правильно задавать направление векторов
отражения. Рассмотрим три наиболее
общих метода. По закону отражения вектор
падающего света, нормаль к поверхности
и вектор отражения лежат в одной
плоскости, причем на этой плоскости
угол падения равен углу отражения. Фонг
вывел отсюда простое решение для случая,
когда свет падает вдоль оси z. Это
предложение удобно для модели освещения
с одним точечным источником. Если начало
системы координат перенести в точку
поверхности, то проекция нормали и
вектора отражения на плоскостьxyбудут лежать на одной прямой (рис 3.8).
Рис. 3.8 – Расчет направления
отражения
Таким образом
, (3.20)
(3.4.1)
где
,,,–x – иy – составляющие единичных
векторов соответственно отражения и
нормали.
Обозначим угол между единичным вектором
нормали и осью z через.Тогда составляющая вектора нормали по
осиzесть
,
где. (3.21)
Аналогично угол между единичным вектором
отражения и осью zравен,
поэтому
.
Известно, что
(3.22)
и
(3.23)
или
(3.24)
Используя отношение x-иy- составляющих
векторов отражения и нормали (3.20) и
соотношение
(3.25)
получаем
(3.26)
Перепишем правую часть:
(3.27)
или
(3.4.10)
.
Из соотношения (3.20) имеем
(3.4.11)
.
Когда свет падает не по оси z(например,
когда источников несколько), таким
методом воспользоваться нельзя. Можно
перенести и повернуть каждый источник
так, чтобы свет падал вдоль осиz;однако проще перенести и повернуть
нормаль так, чтобы она была параллельна
осиz,а точкуРповерхности
принять за начало координат. Тогда
плоскостьхубудет касательной к
поверхности,x-иy– составляющие
единичных векторов падения и отражения
будут иметь разные знаки;z-составляющие
этих векторов, будут, конечно, равны.
Для того чтобы получить результаты в
первоначальной ориентации, надо
выполнить обратное преобразование.
В перемещенной и повернутой системе
координат
;;.
Этот
метод особенно удобен, когда преобразования
реализованы аппаратно или
микропрограммно.
В
третьем методе условие того, что единичная
нормаль, единичный вектор падения и
единичный вектор отражения лежат в
одной плоскости, записывается при помощи
их векторных произведений. Равенство
углов падения и отражения выражается
через скалярные произведения этих
векторов. Из данных условий получаем
(3.28)
или
(nyLz
– nzLy)i
+ (nzLx
– Lznx)j
+ (nxLy
– Lxny)k
=
(nzRy
– nyRz)i
+ (nxRz
– nzRx)j
+ (nyRx
– nxRy)k.
(3.29)
Векторные произведения совпадают, если
равны их х-, у-иz-составляющие:
(3.30)
На первый взгляд
может показаться, что вектор отражения
найден. К сожалению, одно из этих
уравнений всегда является линейно
зависимым.
Запишем
равенство углов падения и отражения:
или
nxRx
+ nyRy+
nzRz
= nxLx+nyLy
+ nzLz,
(3.31)
что дает необходимое добавочное условие.
Матричный вид для всех уравнений с тремя
неизвестными Rx, RyиRzтаков:
или
(3.32)
Поскольку матрица
является квадратной, для решения системы
нужны особые методы.
В частности,
(3.33)
3.5 Модель освещения со спецэффектами
В
модели Варна рассматриваются следующие
спецэффекты:
-
направление;
-
концентрация света;
-
ограничение освещаемой области.
Направление
света можно регулировать независимо
от расположения источника.
Рис. 3.9
Теоретически направленный свет можно
представить как отражение от идеальной
псевдоповерхности при освещении точечным
источником. Направление освещения
объекта можно регулировать наклоном
псевдоповерхности. Т.о., данная модель
освещения может использоваться как для
направленных источников света, так и
для точечных. Количество света, попадающего
в точку Р, зависит от угла.
Пользуясь аппроксимацией Фонга для
зеркального отражения от идеальной
поверхности, найдем интенсивность света
от направленного источника в модели:
.
(3.34)
В модели Варна для достижения эффектов
используются «заслонки» и «конусы».
«Заслонки» обычно ориентированны на
координатные оси, и моделируются путем
ограничения протяженности участка по
осям X,Y,Z(рис.3.10). Если для
точки объекта выполняется неравенствоYmin<Yобъекта<Ymax,
то для нее вычисляется интенсивность,
иначе она игнорируется.
Рис. 3.10
«Конус» позволяет получить четко
очерченное пятно света на объекте.(рис.3.11).
Точка Р объекта освещена, если или
Рис. 3.11
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
У меня есть вектор dir, заданный через x,y,z.
Есть плоскость, которая описана тремя точками {vert0, vert1, vert2}. Т.е. описана треугольником, которая лежит на плоскости.
Мне нужно найти вектор, который получиться при отражении dir от плоскости.
Думаю найти вектор так:
1) получить нормаль к плоскости {vert0,vert1,vert2};
2) получить проекцию dir на нормаль
3) удвоить полученный вектор
4) отнять полученный от исходного вектор dir.
Нормаль я нахожу так:
Сначала получаю два вектора, которые лежат на плоскости:
v0 = vert1-vert0
v1 = vert2-vert0
После вычисляю векторное произведение v0 и v1:
X = v0.Y * v1.Z – v0.Z * v1.Y
Y = v0.Z * v1.X – v0.X * v1.Z
Z = v0.X * v1.Y – v0.Y * v1.X
Теперь мне нужно получить проекцию на эту нормаль, но у меня не получается. Пробовал разные способы, с нормализацией векторов и без. Но что то я делаю не так, видимо.