Модель отражения Блинна – Фонга

редактировать

Модель отражения Блинна – Фонга, также называемая модифицированной моделью отражения Фонга, - это модификация, разработанная Джим Блинн к модели отражения Фонга.

Блинн – Фонг - это модель затенения по умолчанию, используемая в конвейере фиксированных функций OpenGL и Direct3D (до Direct3D 10 и OpenGL 3.1), и выполняется на каждой вершине при передаче по графическому конвейеру ; Значения пикселя между вершинами по умолчанию интерполируются с помощью затенения Гуро, а не более дорогостоящего с точки зрения вычислений затенения Фонга.

Содержание

  • 1 Описание
  • 2 Эффективность
  • 3 примера кода
    • 3.1 Пример кода языка шейдинга высокого уровня
    • 3.2 Пример кода OpenGL Shading Language
      • 3.2.1 Вершинный шейдер
      • 3.2.2 Фрагментный шейдер
  • 4 См. Также
  • 5 Ссылки

Описание

Векторы для расчета затенения Фонга и Блинна – Фонга

При затенении Фонга необходимо постоянно пересчитывать скалярное произведение R ⋅ V {\ displaystyle R \ cdot V}R \ cdot V между зрителем (V) и лучом от источника света (L), отраженным (R) от поверхности.

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

H = L + V ‖ L + V ‖ {\ displaystyle H = {\ frac {L + V} {\ left \ | L + V \ right \ |}}}H = {\ frac {L + V} {\ left \ | L + V \ right \ |}}

R ⋅ V {\ displaystyle R \ cdot V}R \ cdot V можно заменить на N ⋅ H {\ displaystyle N \ cdot H}N \ cdot H , где N {\ displaystyle N}N - это нормализованная нормаль к поверхности. В приведенном выше уравнении L {\ displaystyle L}L и V {\ displaystyle V}V оба являются нормализованными векторами, а H {\ displaystyle H }H- решение уравнения V = PH (- L), {\ displaystyle V = P_ {H} (- L),}V=P_{H}(-L),где PH {\ displaystyle P_ {H}}P_ {H} - это матрица Хаусхолдера, которая отражает точку в гиперплоскости, которая содержит начало координат и имеет нормальный H. {\ displaystyle H.}H.

Это скалярное произведение представляет косинус угла, который составляет половину угла, представленного скалярным произведением Фонга, если V, L, N и R лежат в одной плоскости. Это соотношение между углами остается приблизительно верным, когда векторы не лежат в одной плоскости, особенно когда углы малы. Поэтому угол между N и H иногда называют средним углом.

Учитывая, что угол между вектором на полпути и нормалью к поверхности, вероятно, будет меньше, чем угол между R и V, используемый в модели Фонга (если на поверхность не смотреть под очень крутым углом, для которого она, вероятно, должно быть больше), и поскольку Фонг использует (R ⋅ V) α, {\ displaystyle \ left (R \ cdot V \ right) ^ {\ alpha},}\ left (R \ cdot V \ right) ^ {\ alpha}, an может быть установлен показатель степени α ′>α {\ displaystyle \ alpha ^ {\ prime}>\ alpha}\alpha ^{\prime }>\ alpha таким образом, чтобы (N ⋅ H) α '{\ displaystyle \ left (N \ cdot H \ справа) ^ {\ alpha ^ {\ prime}}}\ left (N \ cdot H \ right) ^ {\ alpha ^ {\ prime}} ближе к предыдущему выражению.

Для поверхностей, освещенных спереди (зеркальные отражения на поверхностях, обращенных к зрителю), α ′ = 4 α {\ displaystyle \ alpha ^ {\ prime} = 4 \, \ alpha}\ alpha ^ {\ prime} = 4 \, \ alpha приведет к появлению зеркальных бликов, которые очень близко соответствуют соответствующим отражениям Фонга. Отражения Фонга всегда круглые для плоской поверхности, отражения Блинна – Фонга становятся эллиптическими, если смотреть на поверхность под крутым углом. Это можно сравнить со случаем, когда солнце отражается в море близко к горизонту или когда далекий уличный фонарь отражается от мокрого тротуара, где отражение всегда будет намного более протяженным по вертикали, чем по горизонтали.

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

Кроме того,, хотя его можно рассматривать как приближение к модели Фонга, он дает более точные модели эмпирически определенных двунаправленных функций распределения отражательной способности, чем Фонга, для многих типов поверхностей.

Эффективность

Блинн-Фонг будет быстрее, чем Фонг, в случае, когда зритель и свет рассматриваются как очень удаленные, например, приближаются или находятся в бесконечности. Это касается направленных источников света и ортогональных / изометрических камер. В этом случае вектор на полпути не зависит от положения и кривизны поверхности просто потому, что вектор на полпути зависит от направления к позиции зрителя и направления к положению источника света, которые индивидуально сходятся на этом удаленном расстоянии, следовательно, можно думать о половинном векторе. как константа в этом случае. H {\ displaystyle H}H, следовательно, можно вычислить один раз для каждого источника света, а затем использовать для всего кадра или, действительно, пока источник света и точка обзора остаются в одном и том же относительном положении. То же самое нельзя сказать о методе Фонга с использованием вектора отражения, который зависит от кривизны поверхности и должен быть пересчитан для каждого пикселя изображения (или для каждой вершины модели в случае вершинного освещения). В 3D-сценах с перспективными камерами такая оптимизация невозможна.

Примеры кода

Пример кода языка высокоуровневого затенения

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

Ниже также необходимо обнулить некоторые скалярные произведения в случае отрицательных ответов. Без этого свет, уходящий от камеры, обрабатывается так же, как и свет, направляющийся к ней. Для расчета зеркального отражения неправильный «ореол» света, отражающегося от краев объекта и от камеры, может казаться таким же ярким, как свет, отражающийся прямо в камеру.

struct Lighting {float3 Diffuse; float3 Specular; }; struct PointLight {позиция float3; float3 diffuseColor; float diffusePower; float3 specularColor; float specularPower; }; Освещение GetPointLight (свет PointLight, float3 pos3D, float3 viewDir, float3 normal) {Lighting OUT; если (light.diffusePower>0) {float3 lightDir = light.position - pos3D; // 3D положение в пространстве поверхности float distance = length (lightDir); lightDir = lightDir / расстояние; // = normalize (lightDir); расстояние = расстояние * расстояние; // Эту линию можно оптимизировать с помощью метода вычисления обратного квадратного корня // Интенсивность рассеянного света. Насыщайте, чтобы не выходить за пределы диапазона 0-1. float NdotL = точка (нормальный, lightDir); интенсивность плавания = насыщение (NdotL); // Вычислить коэффициент рассеянного света с учетом цвета, мощности и ослабления OUT.Diffuse = интенсивность * light.diffuseColor * light.diffusePower / distance; // Вычислить половину вектора между вектором света и вектором обзора. // Обычно это медленнее, чем вычисление фактического вектора отражения // из-за обратного квадратного корня функции нормализации float3 H = normalize (lightDir + viewDir); // Интенсивность зеркального света float NdotH = dot (normal, H); интенсивность = pow (насыщенный (NdotH), specularHardness); // Суммируем коэффициент отражения света OUT.Specular = интенсивность * light.specularColor * light.specularPower / distance; } return OUT; }

Пример кода OpenGL Shading Language

Этот пример на OpenGL Shading Language состоит из двух файлов кода или шейдеров. Первый - это так называемый вершинный шейдер, который реализует затенение Фонга, которое используется для интерполяции нормали поверхности между вершинами. Второй шейдер является так называемым фрагментным шейдером и реализует модель затенения Блинна – Фонга для определения рассеянного и зеркального света от точечного источника света.

вершинный шейдер

Этот вершинный шейдер реализует затенение Фонга :

атрибут vec3 inputPosition; атрибут vec2 inputTexCoord; атрибут vec3 inputNormal; равномерная проекция mat4, modelview, normalMat; варьирующийся vec3 normalInterp; различные vec3 vertPos; void main () {gl_Position = проекция * вид модели * vec4 (inputPosition, 1.0); vec4 vertPos4 = просмотр модели * vec4 (inputPosition, 1.0); vertPos = vec3 (vertPos4) / vertPos4.w; normalInterp = vec3 (normalMat * vec4 (inputNormal, 0,0)); }

Фрагментный шейдер

Этот фрагментный шейдер реализует модель затенения Блинна – Фонга и гамма-коррекцию :

precision mediump float; в vec3 normalInterp; в vec3 vertPos; унифицированный режим int; const vec3 lightPos = vec3 (1.0, 1.0, 1.0); const vec3 lightColor = vec3 (1.0, 1.0, 1.0); const float lightPower = 40.0; const vec3 ambientColor = vec3 (0,1, 0,0, 0,0); const vec3 diffuseColor = vec3 (0,5, 0,0, 0,0); const vec3 specColor = vec3 (1.0, 1.0, 1.0); const float shininess = 16.0; const float screenGamma = 2.2; // Предположим, что монитор откалиброван для цветового пространства sRGB void main () {vec3 normal = normalize (normalInterp); vec3 lightDir = lightPos - vertPos; расстояние с плавающей точкой = длина (lightDir); расстояние = расстояние * расстояние; lightDir = нормализовать (lightDir); float lambertian = max (точка (lightDir, normal), 0,0); float specular = 0,0; если (ламбертовский>0,0) {vec3 viewDir = normalize (-vertPos); // это blinn phong vec3 halfDir = normalize (lightDir + viewDir); float specAngle = max (точка (halfDir, normal), 0,0); specular = pow (specAngle, блеск); // это фонг (для сравнения) if (mode == 2) {vec3lectDir = отражать (-lightDir, normal); specAngle = max (точка (reflectionDir, viewDir), 0,0); // обратите внимание, что показатель степени здесь другой specular = pow (specAngle, shininess / 4.0); }} vec3 colorLinear = ambientColor + diffuseColor * lambertian * lightColor * lightPower / distance + specColor * specular * lightColor * lightPower / distance; // применяем гамма-коррекцию (предположим, что ambientColor, diffuseColor и specColor // были линеаризованы, т.е. в них нет гамма-коррекции) vec3 colorGammaCorrected = pow (colorLinear, vec3 (1.0 / screenGamma)); // использовать цвет с гамма-коррекцией во фрагменте gl_FragColor = vec4 (colorGammaCorrected, 1.0); }

Цвета ambientColor, diffuseColor и specColor не должны подвергаться гамма-коррекции. Если это цвета, полученные из файлов изображений с гамма-коррекцией (JPEG, PNG и т. Д.), Их необходимо линеаризовать перед работой с ними, что осуществляется путем масштабирования канала. значений до диапазона [0, 1] и повышения их до значения гаммы изображения, которое для изображений в цветовом пространстве sRGB можно принять равным примерно 2,2 (даже если для этого конкретного цветового пространства, простое соотношение мощности является лишь приближением фактического преобразования ). Современная графика API имеет возможность автоматически выполнять эту гамма-коррекцию при выборке из текстуры или записи в буфер кадра.

См. Также

Ссылки

Последняя правка сделана 2021-05-12 10:36:26
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте