Рассмотрим, как сделать развевающийся по ветру флаг с реалистичным освещением. Похожая статься есть на gamedev.ru, идею колыхания флага я взял оттуда, но освещение там оставляет желать лучшего. Посмотрим, что тут можно улучшить.
Для начала замечание: я написал две программы.
flag_sw_vp.exe - software vertex processing (на CPU, будет работать даже на RivaTNT)
flag_hw_vp.exe - hardware vertex processing (требует поддержки вершинных шейдеров)
Сам флаг - это полигональная сетка из 12288 полигонов (конечно, можно меньше, но чтобы увидеть, какой выигрыш в скорости дают вершинные шейдеры, я взял так много).
Итак, что нам нужно сделать:
1. Колебания флага, причем чем ближе к флагштоку, тем они должны быть слабее.
2. Изменение нормали для реалистичного освещения.
3. Собственно освещение - диффузное и бликовое.
Структуры шейдера выглядят так (передаем минимум данных)
Cg Vertex Shader:
1
struct VertIn
2
{
3
float4 Position : POSITION;
4
float2 TexCoord : TEXCOORD0;
5
};
6
7
struct VertOut
8
{
9
float4 Position : POSITION;
10
float2 TexCoord : TEXCOORD0;
11
float4 Color : COLOR0;
12
};
Напишем небольшую вспомогательную функцию для расчета колыхания по уравнению колебаний:
Cg Vertex Shader:
float computeDeform(float factor, float time)
{
returnsin(factor * 15 + time * 8) * factor;
}
factor - расстояние от флагштока (фактически это текстурная координата s)
time - время, передается в шейдер как локальный параметр
Пару слов о том, как мы искажаем нормаль. Функция синуса периодическая с диапазоном значений от -1 до 1. Очевидно, что при значении 1 и -1, где точка флага на экстремуме, нормаль должна быть не искажена (это значение (0,0,-1)). Там, где синус равен 0, нормаль фактически смотрит в сторону. Поэтому мы и использовали такое выражение: 1.0f - abs(deform). Оно не совсем правильное, как вы можете видеть. Но по-другому, похоже, не сделаешь - для более правильного вычисления нормали нужна информация о соседних вершинах, а она недоступна в шейдере.
Вот как это выглядит:
В архиве - демка. Для запуска flag_hw_vp.exe вам понадобятся библиотеки cg.dll и cgGL.dll. Я их выкладывать не стал, т.к. весят они около мегабайта.
Спасибо за внимание, и приятных вам шейдеров
Вложение: demo.zip (131.3 кб)
Этот файл был скачан 978 раз. ForestGirl проверилa это вложение на вирусы 03-10-2006 в 05:59
Ты в жизни видел чтобы флаг так развевался? Какие-то ровные вертикальные полосы.. жуть.. Простой анимацией можно сделать гораздо красивее.
У меня заработала только sw-версия. В hw-версии просто есть флагшток и свет, флага нет. Если подставить другие cg.dll и cgGL.dll (у меня их несколько, я уже и не помню, какие откуда качал), то при запуске появляется "failed to load vertex program" (ну или что-то в этом роде). fps везде 62.5.
BUzer писал: Ты в жизни видел чтобы флаг так развевался?
Шейдер тебе в руки Делай реализмъ. Правда, на вторых шейдерах не сделаешь, только на третьих - нужнен доступ к текстуре из вершинной программы.
Цитата:
BUzer писал: Если подставить другие cg.dll и cgGL.dll (у меня их несколько, я уже и не помню, какие откуда качал), то при запуске появляется "failed to load vertex program" (ну или что-то в этом роде).
Странно. Не находит файл flag.cg видимо.
Версия Cg, что я использовал - 1.5b
Цитата:
BUzer писал: fps везде 62.5.
Тоже странно. У меня в св-версии фпс 43 (в хв - 500).
Добавлено 03-10-2006 в 18:05:
Кстати, одну идею по "рандомизации" предложить могу - плавно менять параметр амплитуды по какой-нибудь функции.