Кто занимается графикой, знает, что в эпоху Shader Model 2.0 были очень популярны различные аппроксимации уравнений Френеля, например, аппроксимация Шлика. Если поискать, можно легко их найти в "старых" шейдерах, реализующих там воду или стекло. Не знаю, как в Крайзисе считается, но в эпоху Shader Model 4.0/5.0 уже пора завязывать с этими аппроксимациями и считать подобные вещи честно. На самом деле вычислений здесь - кот наплакал. Если подразумевается использование преломлённого луча, то это значит что у нас уже есть косинусы углов падения и преломления. Придётся сделать всего семь умножений, два деления, плюс пять арифметических операций сложения/вычитания, чтобы получить коэффициент для неполяризованного света. Если преломления не считаются, а есть только угол падения, придётся использовать вариант с трансцендентными функциями. В этом случае формулу лучше запечь в текстуру и делать в шейдере выборку. Впрочем, первый вариант тоже является кандидатом на запекание в текстуру: cами по себе расчёты не сложны и не займут много инструкций (по нынешним меркам), но по моим предварительным оценкам, сложный шейдер, реализующий правдоподобный эффект преломления, выльется этак в 400-500 инструкций. В этих условиях целесообразнее сделать дополнительную выборку из текстуры, заодно и соотношение ALU/TEX будет выполняться получше.
Я написал тест, чтобы проверить, как распространяется эффект Френеля на энергию луча (и отладить математику, отлаживать её в прямо в шейдере - то ещё удовольствие). Вот скриншоты, показывающие преломление/отражение для воздуха и стекла:
Случай, когда центральный луч падает перпендикулярно поверхности. Видно, что почти вся энергия луча поглощается, и мало что отражается. Отражают и преломляют обе поверхности стекла:
При значительных углах видно, что отражённый луч получает все большую долю энергии падающего луча:
Почти предельный случай: почти вся энергия луча вкладывается в отражения (первое и второе).
А вот графики функций для стекла (по оси абсцисс - угол падения, по оси ординат - значение коэффициента). Для s-polarized (синий цвет) и p-polarized (красный):
А вот усреднённое значение для неполяризованного света:
Думаю, с Френелем всё понятно (для CG-случая, физическая сторона вопроса очень глубока).
P. S. Реализовал трассировку луча для линзы, наполненной водой. Вот как это выглядит:
Хорошо видны две "мертвые зоны" по бокам обзора. Также хорошо видно, как странно ведёт себя луч рядом с этими зонами. Поэкспериментируйте - налейте в стеклянную бутыль воды и посмотрите, как искажается изображение на мониторе. А потом сравните с картинкой. Я сравнивал - всё правильно :)
Комментариев нет:
Отправить комментарий