После того, как я некоторое время писал «стандартные» шейдеры phong & blinn, я недавно начал заниматься физическим шейдингом. Ресурс, который мне очень помог, - это заметки о курсе , особенно эта статья, в которой объясняется, как сделать блины более правдоподобными.
Я реализовал модель blinn, изложенную в статье, и мне очень нравится, как она выглядит. Наиболее существенным предложенным изменением (imo) является включение коэффициента отражения Френеля, и это также та часть, которая доставляет мне проблемы. К сожалению, автор решил сосредоточиться только на зеркальной части, исключив диффузное отражение. Учитывая, например, диффузное отражение Ламберта, я просто не знаю, как объединить его с «улучшенным» блином - потому что простое добавление рассеянных и зеркальных частей кажется неправильным.
В некоторых шейдерах я видел «термин Френеля» с плавающей точкой в диапазоне 0 - 1, основанный на показателях преломления участвующих сред. Аппроксимация Шлика используется каждый раз:
float schlick( in vec3 v0, in vec3 v1, in float n1, in float n2 )
{
float f0 = ( n1 - n2 ) / ( n1 + n2 );
f0 *= f0;
return f0 + ( 1 - f0 ) * pow( dot( v0, v1 ), 5 );
}
Делая это таким образом, можно затем линейно интерполировать между диффузным и зеркальным вкладом на основе члена Френеля, например
float fresnel = schlick( L, H, 1.0002926 /*air*/, 1.5191 /*other material*/ );
vec3 color = mix( diffuseContrib, specularContrib, fresnel );
В статье автор заявляет, что этот подход неверен - потому что он в основном просто затемняет зеркальный цвет всякий раз, когда L параллелен или почти параллелен H - и что вместо вычисления f0 на основе показателей преломления вы должны рассматривать зеркальное отражение раскрасьте себя как f0 и сделайте, чтобы ваше приближение schlick вычислило vec3, например так:
vec3 schlick( in vec3 v0, in vec3 v1, in vec3 spec )
{
return spec + ( vec3( 1.0 ) - spec ) * pow( dot( v0, v1 ), 5 );
}
Это приводит к зеркальному цвету, идущему к белому под скользящими углами.
Теперь мой вопрос: как бы я ввел диффузный компонент в это? При 90 ° зеркальный вклад полностью белый, это означает, что весь входящий свет отражается, поэтому не может быть рассеянного вклада. Для углов падения <90 ° могу ли я просто умножить всю диффузную часть на (vec3 (1) - schlick), то есть на долю света, который не отражается?
vec3 diffuseContrib = max( dot( N, L ), 0.0 ) * kDiffuse * ( vec3( 1.0 ) - schlick( L, H, kSpec ) );
Или мне нужен совершенно другой подход?
Ответы:
Краткий ответ:
Это выглядит достаточно хорошо?
Да, сохрани.
Нет - возиться с этим еще немного.
Длинный ответ:
Для получения точного реалистичного физического затенения требуется больше ресурсов графического процессора, чем это возможно, вам всегда придется прибегать к фальшивым вещам по той простой причине, что компьютер не может имитировать всю вселенную, даже весь спектр видимого света.
Это «сверхъестественная долина» затенения.
Не только из-за окружающего освещения и окклюзии, но, например, из-за внешней среды, как дневного, так и лунного света, имеется огромное количество света ультрафиолетового спектра, крошечная часть которого возвращается в видимый спектр различными материалами, в основном органическими. Различные типы люминесцентных ламп и HID также излучают большое количество ультрафиолета.
Эффект незаметен, но благодаря годам эволюции мозг инстинктивно обрабатывает его, поскольку это означало разницу между хорошей едой и, возможно, долгой мучительной смертью, поэтому, если что-то немного не в нашем мозгу, звучит сигнал «что-то не так» ,
Мультипликационные, нереалистичные и почти реалистичные, но намеренно отклоненные от нормы (например, Halo) художественные стили избегают этой проблемы.
Другая проблема заключается в том, что ни у двух людей нет ни одного присутствия рецептора RYGBL, ни кривой отклика, в то время как мониторы строго RGB и поэтому не могут идеально воспроизводить изображения для всех людей. (Красный, Желтый, Зеленый, Синий и Лума, см. Тетрахроматизм - http://en.wikipedia.org/wiki/Tetrachromacy )
Неважно, насколько усердно вы работаете, в этом будет «что-то не так» и есть место для улучшения, по крайней мере, для кого-то где-то.
И это одна из причин, почему существует так много моделей затенения.
Из-за всего этого хороший художник всегда заканчивает тем, что обманывает уровни освещения и светового отклика в окружающей среде, чтобы в какой-то степени достичь «достаточно хорошего» результата (он никогда не бывает идеальным), просто предоставьте им доступ к настройкам и обманите их путь к приятным результатам.
источник