HLFX.Ru Forum (https://hlfx.ru/forum/index.php)
- OpenGL (https://hlfx.ru/forum/forumdisplay.php?forumid=7)
-- Развевающийся флаг (https://hlfx.ru/forum/showthread.php?threadid=405)
Отправлено XaeroX 03-10-2006 в 05:43:
Развевающийся флаг
Рассмотрим, как сделать развевающийся по ветру флаг с реалистичным освещением. Похожая статься есть на 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:
3 | float4 Position : POSITION; |
4 | float2 TexCoord : TEXCOORD0; |
9 | float4 Position : POSITION; |
10 | float2 TexCoord : TEXCOORD0; |
11 | float4 Color : COLOR0; |
Напишем небольшую вспомогательную функцию для расчета колыхания по уравнению колебаний:
Cg Vertex Shader:
float computeDeform(float factor, float time) |
return sin(factor * 15 + time * 8) * factor; |
factor - расстояние от флагштока (фактически это текстурная координата s)
time - время, передается в шейдер как локальный параметр
А вот сам код шейдера:
Cg Vertex Shader:
1 | VertOut main(VertIn vin, |
2 | uniform float Amplitude: C0, |
3 | uniform float TimeFactor: C1, |
4 | uniform float4 LightPos: C2, |
5 | uniform float3 EyePos: C3, |
6 | uniform float3 LightColor: C4) |
13 | deform = computeDeform(vin.TexCoord.x, TimeFactor); |
14 | vin.Position.z = deform * Amplitude; |
15 | normal.x = 1.0f - abs(deform); |
18 | normal = normalize(normal); |
22 | float dist, attn, diffuse, specular; |
24 | L2V = LightPos.xyz - vin.Position.xyz; |
27 | E2V = normalize(EyePos.xyz - vin.Position.xyz); |
28 | HAV = normalize((E2V + L2V) * 0.5f); |
30 | attn = 1.0f - dist / LightPos.w; |
31 | diffuse = dot(L2V, normal); |
32 | specular = pow(saturate(dot(HAV, normal)),20); |
34 | vout.Position = mul(glstate.matrix.mvp, vin.Position); |
35 | vout.TexCoord = vin.TexCoord; |
36 | vout.Color.rgb = (diffuse + specular) * attn * LightColor.rgb; |
Пару слов о том, как мы искажаем нормаль. Функция синуса периодическая с диапазоном значений от -1 до 1. Очевидно, что при значении 1 и -1, где точка флага на экстремуме, нормаль должна быть не искажена (это значение (0,0,-1)). Там, где синус равен 0, нормаль фактически смотрит в сторону. Поэтому мы и использовали такое выражение: 1.0f - abs(deform). Оно не совсем правильное, как вы можете видеть. Но по-другому, похоже, не сделаешь - для более правильного вычисления нормали нужна информация о соседних вершинах, а она недоступна в шейдере.
Вот как это выглядит:
В архиве - демка. Для запуска flag_hw_vp.exe вам понадобятся библиотеки cg.dll и cgGL.dll. Я их выкладывать не стал, т.к. весят они около мегабайта.
Спасибо за внимание, и приятных вам шейдеров __________________
Отправлено BUzer 03-10-2006 в 10:51:
Ты в жизни видел чтобы флаг так развевался? Какие-то ровные вертикальные полосы.. жуть.. Простой анимацией можно сделать гораздо красивее.
У меня заработала только sw-версия. В hw-версии просто есть флагшток и свет, флага нет. Если подставить другие cg.dll и cgGL.dll (у меня их несколько, я уже и не помню, какие откуда качал), то при запуске появляется "failed to load vertex program" (ну или что-то в этом роде). fps везде 62.5.
Отправлено XaeroX 03-10-2006 в 11:05:
Цитата:
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:
Кстати, одну идею по "рандомизации" предложить могу - плавно менять параметр амплитуды по какой-нибудь функции.__________________
Отправлено BUzer 03-10-2006 в 12:49:
XaeroX
Цитата:
Шейдер тебе в руки
Делай реализмъ.
Алгоритм-бы придумать.. У меня было желание сделать скринсейвер с развевающимся флагом, но я так и не продумал физическую модель
Цитата:
Правда, на вторых шейдерах не сделаешь, только на третьих - нужнен доступ к текстуре из вершинной программы.
А это зачем?
Отправлено XaeroX 03-10-2006 в 13:31:
Цитата:
BUzer писал:
А это зачем?
Шумовую текстуру юзать
А как еще неравномерность задавать?
В GLSL есть правда ф-я noise, но в Cg ее нет __________________
Отправлено exelents 05-02-2007 в 08:38:
Люди, скиньте пожалуйста cg.dll
Или где его взять? В НВидия СДК его не нашел. И в OpenGLSDK тоже нет
Отправлено XaeroX 05-02-2007 в 08:56:
exelents тебе нужен Cg Toolkit. Смотри вот тут:
http://developer.nvidia.com/object/...it-15#downloads
__________________