Из Википедии, свободной энциклопедии
  (Перенаправлено из модели затенения Блинн-Фонга )
Перейти к навигации Перейти к поиску

Модель отражения Блинна – Фонга , также называемая модифицированной моделью отражения Фонга, представляет собой модификацию, разработанную Джимом Блинном для модели отражения Фонга . [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  /  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]

См. Также [ править ]

  • Список распространенных алгоритмов затенения
  • Модель отражения Фонга для соответствующей модели Фонга
  • Гамма-коррекция
  • Зеркальное выделение

Ссылки [ править ]

  1. ^ Джеймс Ф. Блинн (1977). «Модели отражения света для изображений, синтезированных на компьютере». Proc. 4-я ежегодная конференция по компьютерной графике и интерактивным техникам : 192–198. CiteSeerX  10.1.1.131.7741 . DOI : 10.1145 / 563858.563893 .
  2. ^ Шрейнер, Дэйв; Рабочая группа Khronos OpenGL ARB (2010). «Математика освещения». Руководство по программированию OpenGL: официальное руководство по изучению OpenGL версий 3.0 и 3.1 (7-е изд.). Pearson Education, Inc., стр. 240–245. ISBN 978-0-321-55262-4.
  3. ^ Крус, Кристофер (2014), Модель волн и модель судна для моделирования состояния моря , Университет Линчёпинга , стр. 97
  4. ^ Нган, Адди; Дюран, Фредо; Матусик, Войцех (2004). «Экспериментальная проверка аналитических моделей BRDF» . ACM SIGGRAPH 2004 Наброски на - SIGGRAPH '04 . ACM Press. DOI : 10.1145 / 1186223.1186336 . Проверено 23 апреля 2019 года .
  5. ^ "Пример WebGL: Затенение Фонга / Блинна Фонга" . www.mathematik.uni-marburg.de . Проверено 13 сентября 2019 .
  6. ^ https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_framebuffer_sRGB.txt