Эта статья, возможно, содержит оригинальные исследования . ( Январь 2012 г. ) ( Узнайте, как и когда удалить этот шаблон сообщения ) |
Модель отражения Блинна – Фонга , также называемая модифицированной моделью отражения Фонга, представляет собой модификацию, разработанную Джимом Блинном для модели отражения Фонга . [1]
Блинн – Фонг - это модель затенения по умолчанию, используемая в конвейере фиксированных функций OpenGL и Direct3D (до Direct3D 10 и OpenGL 3.1), и выполняется на каждой вершине при передаче по графическому конвейеру ; значения пикселей между вершинами по умолчанию интерполируются с помощью затенения Гуро , а не затенения Фонга, требующего больших вычислительных затрат . [2]
Описание [ править ]
При затенении Фонга необходимо постоянно пересчитывать скалярное произведение между наблюдателем ( V ) и лучом от источника света ( L ), отраженным ( R ) от поверхности.
Если вместо этого вычислить средний вектор между векторами наблюдателя и источника света,
можно заменить на , где - нормализованная нормаль к поверхности. В приведенном выше уравнении, и являются нормализованными векторами и являются решением уравнения, где - матрица Хаусхолдера, которая отражает точку на гиперплоскости, которая содержит начало координат и имеет нормаль
Этот скалярный продукт представляет собой косинус угла, который составляет половину угла, представленного скалярным произведением Фонга, если V , L , N и R лежат в одной плоскости. Это соотношение между углами остается приблизительно верным, когда векторы не лежат в одной плоскости, особенно когда углы малы. Поэтому угол между N и H иногда называют половинным углом.
Учитывая, что угол между вектором на полпути и нормалью к поверхности, вероятно, будет меньше, чем угол между R и V, используемый в модели Фонга (если на поверхность не смотреть под очень крутым углом, для которого он, вероятно, будет больше), и поскольку Фонг использует в показатель может быть установлено таким образом, что ближе к прежнему выражению.
Для поверхностей с передним освещением (зеркальные отражения на поверхностях, обращенных к зрителю) приведет к зеркальным бликам, которые очень близко соответствуют соответствующим отражениям Фонга. Однако, в то время как отражения Фонга всегда круглые для плоской поверхности, отражения Блинна – Фонга становятся эллиптическими, если смотреть на поверхность под крутым углом. Это можно сравнить со случаем, когда солнце отражается в море близко к горизонту, или когда далекий уличный фонарь отражается от мокрого тротуара, где отражение всегда будет намного более протяженным по вертикали, чем по горизонтали. [3]
Кроме того, хотя его можно рассматривать как приближение к модели Фонга, он дает более точные модели эмпирически определенных функций распределения двунаправленной отражательной способности, чем Фонг, для многих типов поверхностей. [4]
Эффективность [ править ]
Блинн-Фонг будет быстрее, чем Фонг, в случае, когда зритель и свет рассматриваются как очень удаленные, например, приближаются или находятся на бесконечности. Это относится к направленным источникам света и ортогональным / изометрическим камерам. В этом случае вектор на полпути не зависит от положения и кривизны поверхности просто потому, что вектор на полпути зависит от направления к позиции зрителя и направления к положению источника света, которые индивидуально сходятся на этом удаленном расстоянии, следовательно, можно думать о половинном векторе как константа в этом случае.следовательно, их можно вычислить один раз для каждого источника света, а затем использовать для всего кадра или, действительно, пока свет и точка обзора остаются в одном и том же относительном положении. То же самое не относится к методу Фонга с использованием вектора отражения, который зависит от кривизны поверхности и должен быть пересчитан для каждого пикселя изображения (или для каждой вершины модели в случае вершинного освещения). В 3D-сценах с перспективными камерами такая оптимизация невозможна.
Примеры кода [ править ]
Пример кода языка высокоуровневого затенения [ править ]
Эта статья, возможно, содержит оригинальные исследования . ( Июнь 2011 г. ) ( Узнайте, как и когда удалить этот шаблон сообщения ) |
Этот пример на языке затенения высокого уровня представляет собой метод определения рассеянного и зеркального света от точечного источника света. Световая структура, положение в пространстве поверхности, вектор направления взгляда и нормаль к поверхности пропускаются. Возвращается структура освещения;
Ниже также необходимо обнулить некоторые скалярные произведения в случае отрицательных ответов. Без этого свет, уходящий от камеры, обрабатывается так же, как и свет, направляющийся к ней. Для расчета зеркального отражения неправильный «ореол» света, отражающегося от краев объекта и от камеры, может казаться таким же ярким, как свет, отражающийся непосредственно в камеру.
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 / 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имеют возможность выполнять эту гамма-коррекцию автоматически при выборке из текстуры или записи в буфер кадра . [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