Модель отражения Блинна – Фонга , также называемая модифицированной моделью отражения Фонга, представляет собой модификацию, разработанную Джимом Блинном для модели отражения Фонга . [1]
Блинн – Фонг - это модель затенения по умолчанию, используемая в конвейере фиксированных функций OpenGL и Direct3D (до Direct3D 10 и OpenGL 3.1), и выполняется на каждой вершине при передаче по графическому конвейеру ; значения пикселей между вершинами по умолчанию интерполируются с помощью затенения Гуро , а не затенения Фонга, требующего больших вычислительных затрат . [2]
Описание
При затенении Фонга необходимо постоянно пересчитывать скалярное произведение между зрителем ( V ) и лучом от источника света ( L ), отраженным ( R ) от поверхности.
Если вместо этого вычислить средний вектор между векторами наблюдателя и источника света,
можно заменить на , где - нормализованная нормаль к поверхности. В приведенном выше уравнении а также оба являются нормализованными векторами, и является решением уравнения где это матрица Хаусхолдера , которая отражает точку в гиперплоскости, содержащей начало координат и имеет нормальный
Этот скалярный продукт представляет собой косинус угла, который составляет половину угла, представленного скалярным произведением Фонга, если V , L , N и R лежат в одной плоскости. Это соотношение между углами остается приблизительно верным, когда векторы не лежат в одной плоскости, особенно когда углы малы. Поэтому угол между N и H иногда называют половинным углом.
Учитывая, что угол между вектором на полпути и нормалью к поверхности, вероятно, будет меньше, чем угол между R и V, используемый в модели Фонга (если только поверхность не рассматривается под очень крутым углом, для которого он, вероятно, будет больше), и поскольку Фонг используетпоказатель может быть установлен такой, что ближе к прежнему выражению.
Для поверхностей с фронтальным освещением (зеркальные отражения на поверхностях, обращенных к зрителю), приведет к появлению зеркальных бликов, которые очень точно соответствуют соответствующим отражениям Фонга. Однако, в то время как отражения Фонга всегда круглые для плоской поверхности, отражения Блинна – Фонга становятся эллиптическими, если смотреть на поверхность под крутым углом. Это можно сравнить со случаем, когда солнце отражается в море близко к горизонту, или когда далекий уличный фонарь отражается от мокрого тротуара, где отражение всегда будет намного более протяженным по вертикали, чем по горизонтали. [3]
Кроме того, хотя его можно рассматривать как приближение к модели Фонга, он дает более точные модели эмпирически определенных функций распределения двунаправленной отражательной способности, чем Фонг, для многих типов поверхностей. [4]
Эффективность
Блинн-Фонг будет быстрее, чем Фонг, в случае, когда зритель и свет рассматриваются как очень удаленные, например, приближаются или находятся на бесконечности. Это относится к направленным источникам света и ортогональным / изометрическим камерам. В этом случае вектор на полпути не зависит от положения и кривизны поверхности просто потому, что вектор на полпути зависит от направления к позиции зрителя и направления к положению источника света, которые индивидуально сходятся на этом удаленном расстоянии, следовательно, можно думать как константа в этом случае.следовательно, их можно вычислить один раз для каждого источника света, а затем использовать для всего кадра или, действительно, пока свет и точка обзора остаются в одном и том же относительном положении. То же самое не относится к методу Фонга с использованием вектора отражения, который зависит от кривизны поверхности и должен быть пересчитан для каждого пикселя изображения (или для каждой вершины модели в случае вершинного освещения). В 3D-сценах с перспективными камерами такая оптимизация невозможна.
Примеры кода
Пример кода языка высокоуровневого затенения
Этот образец на языке затенения высокого уровня представляет собой метод определения рассеянного и зеркального света от точечного источника света. Световая структура, положение в пространстве поверхности, вектор направления взгляда и нормаль к поверхности пропускаются. Возвращается структура освещения;
Ниже также необходимо обнулить некоторые скалярные произведения в случае отрицательных ответов. Без этого свет, уходящий от камеры, обрабатывается так же, как и свет, направляющийся к ней. Для расчета зеркального отражения неправильный «ореол» света, отражающегося от краев объекта и от камеры, может казаться таким же ярким, как свет, отражающийся непосредственно в камеру.
struct Lighting { float3 Diffuse ; float3 Зеркальное ; };struct PointLight { позиция float3 ; float3 diffuseColor ; float diffusePower ; float3 specularColor ; float specularPower ; }; Освещение GetPointLight ( свет PointLight , float3 pos3D , float3 viewDir , float3 normal ) { Lighting OUT ; if ( light . diffusePower > 0 ) { float3 lightDir = light . позиция - pos3D ; // 3D положение в пространстве поверхности float distance = length ( lightDir ); lightDir = lightDir / расстояние ; // = normalize (lightDir); расстояние = расстояние * расстояние ; // Эту строку можно оптимизировать с помощью метода вычисления обратного квадратного корня // Интенсивность рассеянного света. Насыщайте, чтобы не выходить за пределы диапазона 0-1. float NdotL = точка ( нормальный , lightDir ); интенсивность плавания = насыщение ( NdotL ); // Рассчитываем коэффициент рассеянного света по цвету света, мощности и затуханию OUT . Рассеянный = интенсивность * свет . diffuseColor * светлый . diffusePower / distance ;// Вычислить половину вектора между вектором света и вектором обзора. // Обычно это медленнее, чем вычисление фактического вектора отражения // из-за обратного квадратного корня функции нормализации float3 H = normalize ( lightDir + viewDir );// Интенсивность зеркального света float NdotH = dot ( normal , H ); интенсивность = pow ( насыщенный ( NdotH ), specularHardness );// Суммируем факторинг зеркального света OUT . Зеркальное отражение = интенсивность * свет . specularColor * светлый . specularPower / distance ; } return OUT ; }
Пример кода OpenGL Shading Language
Этот пример на языке шейдеров OpenGL состоит из двух файлов кода или шейдеров . Первый - это так называемый вершинный шейдер, который реализует затенение Фонга , которое используется для интерполяции нормали к поверхности между вершинами. Второй шейдер является так называемым фрагментным шейдером и реализует модель затенения Блинна – Фонга для определения рассеянного и зеркального света от точечного источника света.
Вершинный шейдер
Этот вершинный шейдер реализует затенение Фонга :
атрибут vec3 inputPosition ; атрибут vec2 inputTexCoord ; атрибут vec3 inputNormal ;равномерное mat4 проекция , вид модель , normalMat ;варьирующийся vec3 normalInterp ; варьирующийся vec3 vertPos ;void main () { gl_Position = проекция * вид модели * vec4 ( inputPosition , 1.0 ); vec4 vertPos4 = просмотр модели * vec4 ( inputPosition , 1.0 ); вертПос = vec3 ( вертПос4 ) / вертПос4 . w ; normalInterp = vec3 ( normalMat * vec4 ( inputNormal , 0,0 )); }
Фрагментный шейдер
Этот фрагментный шейдер реализует модель затенения Блинна – Фонга [5] и гамма-коррекцию :
прецизионный поплавок среднего размера ;в 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 ; // Предположим, что монитор откалиброван для цветового пространства sRGBvoid main () { vec3 normal = нормализовать ( normalInterp ); vec3 lightDir = lightPos - vertPos ; расстояние с плавающей точкой = длина ( lightDir ); расстояние = расстояние * расстояние ; lightDir = нормализовать ( lightDir ); float lambertian = max ( dot ( lightDir , normal ), 0,0 ); float specular = 0,0 ; if ( ламбертовский > 0,0 ) { vec3 viewDir = normalize ( - vertPos ); // это blinn phong vec3 halfDir = normalize ( lightDir + viewDir ); float specAngle = max ( точка ( halfDir , normal ), 0,0 ); specular = pow ( specAngle , блеск ); // это Фонг (для сравнения) , если ( режим == 2 ) { vec3 reflectDir = отражения ( - lightDir , нормальная ); specAngle = max ( точка ( reflectionDir , viewDir ), 0,0 ); // обратите внимание , что показатель отличается здесь зеркальный = пау ( specAngle , Блеск / 4,0 ); } } Vec3 colorLinear = ambientColor + DiffuseColor * Lambertian * lightColor * lightPower / Расстояние + specColor * зеркальная * lightColor * lightPower / расстояние ; // применяем гамма-коррекцию (предположим, что 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 имеют возможность автоматически выполнять эту гамма-коррекцию при выборке из текстуры или записи в буфер кадра . [6]
Смотрите также
- Список распространенных алгоритмов затенения
- Модель отражения Фонга для соответствующей модели Фонга
- Гамма-коррекция
- Зеркальное выделение
Рекомендации
- ^ Джеймс Ф. Блинн (1977). «Модели отражения света для изображений, синтезированных на компьютере». Proc. 4-я ежегодная конференция по компьютерной графике и интерактивным техникам : 192–198. CiteSeerX 10.1.1.131.7741 . DOI : 10.1145 / 563858.563893 .
- ^ Шрейнер, Дэйв; Рабочая группа Khronos OpenGL ARB (2010). «Математика освещения». Руководство по программированию OpenGL: официальное руководство по изучению OpenGL версий 3.0 и 3.1 (7-е изд.). Pearson Education, Inc., стр. 240–245. ISBN 978-0-321-55262-4.
- ^ Крус, Кристофер (2014), Модель волн и модель плавсредства для моделирования состояния моря , Университет Линчёпинга , стр. 97
- ^ Нган, Адди; Дюран, Фредо; Матусик, Войцех (2004). «Экспериментальная проверка аналитических моделей BRDF» . ACM SIGGRAPH 2004 Наброски на - SIGGRAPH '04 . ACM Press. DOI : 10.1145 / 1186223.1186336 . Проверено 23 апреля 2019 года .
- ^ «Пример WebGL: Затенение Фонга / Блинна Фонга» . www.mathematik.uni-marburg.de . Проверено 13 сентября 2019 .
- ^ https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_framebuffer_sRGB.txt