На одном из слайдов «Рендеринг DirectX 11 в Battlefield 3» в PowerPoint я заметил следующий код:
struct Light {
float3 pos; float sqrRadius;
float3 color; float invSqrRadius;
}
Я не понимаю, почему они хранят квадрат радиуса и даже обратный квадрат (который я считаю просто радиусом в 1 квадрат) вместо простого сохранения радиуса? Как они используют эти данные в своих вычислениях? Кроме того, как насчет конуса и линейного освещения? Эта структура должна быть только для точечных источников света, я не вижу, чтобы она работала для других типов - нет достаточных данных. Тем не менее, я хотел бы знать, как они используют этот квадрат и invSquare.
ОБНОВЛЕНИЕ: Хорошо, я наконец получил это.
Вот классическое уравнение ослабления света, которое легко найти в сети:
float3 lightVector = lightPosition - surfacePosition;
float attenuation = saturate(1 - length(lightVector)/lightRadius);
Это относительно дорого, поскольку length(lightVector)
фактически делает это:
length(lightVector) = sqrt(dot(lightVector, lightVector);
Более того, операция деления (/lightRadius)
также довольно затратна.
Вместо того, чтобы вычислять ослабление света таким образом, вы можете вычислить его следующим образом, который будет намного быстрее:
attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);
где invRadiusSqr может быть предварительно вычислен на уровне процессора и передан как константа шейдера.
Более того, в результате вы получаете квадратичное затухание света (вместо линейного в первом случае), что даже лучше, поскольку свет IRL показал квадратичный спад.
Спасибо всем за вашу помощь!
Ответы:
Это просто своего рода оптимизация, учитывая, что
invSqrRadius = 1/SqrRadius
вместо вычисления обратного квадрата радиуса для каждого источника света каждый раз, когда они просто кешируют его, причина в том, что деление обычно является «медленной» операцией, по крайней мере, по сравнению с умножением.Эта оптимизация актуальна особенно:
Относительно того, как это используется, я не уверен относительно их конкретной реализации, но относительно того
1/sqrRadius
, что это просто используется для ослабления света, спада и отбраковки. Это также актуально для направленного и точечного освещения, единственное различие в случае прожектора состоит в том, что вам необходимо вычислить коэффициент прожектора после применения затухания . Что касается направленного света, такого как солнце, оно обычно не имеет никакого затухания или спада, поэтому я думаю, оно будет проигнорировано.[РЕДАКТИРОВАТЬ] Просто, чтобы уточнить, это не несущественные данные. Излучение света может быть рассчитано с использованием следующего уравнения:
Это уравнение объясняет, почему количество получаемой энергии уменьшается с квадратом расстояния.
Другой момент - вам нужно вычислить расстояние между вершиной и светом, чтобы рассчитать вклад света в конкретную вершину (маловероятно, что это значение будет кэшировано), вершина может находиться в или вне светового диапазона, что приводит нас к следующей точке. где
Radius Square
полезно для выбраковки.Если вам нужен практический пример для расчета ослабления света и отбраковки, это особенно полезно в отложенных средствах рендеринга на основе плиток, вот один пример .
источник
invSqrRadius не 1 - sqrRadius; это 1 / sqrRadius.
Это означает, что вы можете умножить на invSqrRadius вместо деления на sqrRadius (поскольку деление обычно намного дороже, чем умножение)
источник
Другие ответы здесь касались обратного квадратного радиуса, но вместо этого я собираюсь взглянуть на квадрат радиуса (который затрагивал concept3d, но я полагаю, что он заслуживает дальнейшего обсуждения).
Для чего полезны квадраты - это сравнение расстояний. Мы знаем, что при расчете расстояния между двумя точками используется квадратный корень, и квадратные корни очень дороги для вычисления, но если все, что мы хотим сделать, это сравнить расстояния (чтобы найти, что меньше или больше, и сделать что-то интересное на основе результат) мы можем выбросить квадратный корень.
Если sqrt (x)> sqrt (y), то это также тот случай, когда x> y.
Для света квадрат радиуса такой же, как расстояние между центром света и его максимальной протяженностью - в квадрате, конечно.
Для расчетов освещения это может быть использовано для раннего случая. Если расстояние между точкой, которую вы освещаете, и центром источника света (в квадрате) больше, чем радиус в квадрате, точка не получает света, и вам не нужно выполнять остальные вычисления. Таким образом, это всего лишь оптимизация (довольно распространенная) - мы можем использовать квадрат радиуса для сравнения расстояний без дорогих квадратных корней и ценой только вычитания и точечного произведения.
Я, конечно, не знаю, использует ли это именно BF3, но я ожидаю, что я не слишком далеко от цели.
источник