![]() |
|
![]() |
![]() |
Новости | Конференция | Чат | База данных | Творчество | Сообщество | О сайте | English |
![]() |
Помощь сайту |
![]() |
![]() |
![]() |
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BUMP MAPPING ![]() Итак, что это такое? Скорее всего, о bump mapping`е вы слышали. Он позволяет улучшить качество картинки, создавая иллюзию того, что на объекте находится множество мелких неровностей/царапин и т.п. Этот эффект может быть выполнен несколькими способами, но в современных играх используются несколько особенных. Bump mapping, который есть в 3д пакетах использует карту высот (серая текстура), это не в последнюю очередь сделано для удобства пользователя… Но с real-time техникой чуть по-другому. NORMAL MAPPING Вообще 3D API, такие как OpenGL и DirectX, используют при расчете освещения нормали (вектора перпендикулярные полигонам) для каждой вершины. Идея normal mapping`а заключается в том, чтобы задавать эти нормали не только для каждой вершины, но и для каждого пикселя. ![]() Нормали кодируют в цвет и выходит normal map – текстура ядовито-фиолетового цвета. Рассчитать освещение попиксельно позволяют пиксельные шейдеры. Для просчетов используется пространство касательных – нормаль, бинормаль и тангенс, которые просчитываются заранее (с помощью утилиты NVMeshMender) и хранятся вместе с моделью (есть вариант, когда хранятся не все три вектора нормаль, бинормаль и тангенс, а два – нормаль, и любой из двух других; третий вектор можно восстановить в вершинном шейдере). Алгоритм для вершинного шейдера: На вход идет: - позиция камеры в локальной системе координат модели, которая рисуется - позиция источника света в локальной системе координат модели, которая рисуется 1)Вычислить вектор источника света 2)Нормализировать его 3)Трансформировать вектор источника света в пространство касательных. 4)Вычислить вектор камеры 5)Нормализировать его 6)Просчитать H вектор (смотрите модели освещения Blinn`а; H half-angle vector) 7)Трансформировать H вектор в пространство касательных. На выход идет: - вектор источника света в пространстве касательных - H вектор в пространстве касательных Алгоритм для пиксельного шейдера: На вход идет: - вектор источника света в пространстве касательных - H вектор в пространстве касательных - Color цвет - Ambient, который считается по формуле: Ambient = li.Ambient * ma.Ambient + li.Ambient * ma.WordlAmbient (ma – текущий материал, li – текущий источник света) - Diffuse, который считается по формуле: Diffuse= li.Diffuse*ma.Diffuse - Specular, который считается по формуле: Specular = li. Specular *ma. Specular - Shininess материала (интенсивность Specular) ВНИМАНИЕ! Это для модели освещения, которая принята в OpenGL. 1) Нормализировать вектор источника света в пространстве касательных 2) Нормализировать Н вектор в пространстве касательных ПРИМЕЧАНИЕ. Да, да, я знаю Н вектор и вектор источника света мы уже нормализировали в вершинном шейдере.. но в пиксельном шейдере идет уже не тоот вектор – он интерполируется по полигону для каждого пикселя, так что нормализировать его нужно. 3) Прочитать из normal текстуры и превести к норме по формуле перевода цвета в вектор 4) Просчитать dot product (скалярное произведение) вектора нормали из normal текстуры и вектора источника света в пространстве касательных 5) Просчитать dot product (скалярное произведение) вектора нормали из normal текстуры и Н вектора в пространстве касательных 6) Просчитать цвет с помощью diffuse (входного параметра) 7) Прочитать цвет из Diffuse текстуры 8) Просчитать Specular с учетом Shininess 9) Просчитать финальный результат diffuse * specular в границах [0..1] РЕАЛИЗАЦИЯ НА OPENGL Вершинный шейдер: !!ARBvp1.0 OPTION ARB_position_invariant; говорим, что изменять вершины не будем PARAM light = program.local[0]; PARAM eye = program.local[1]; PARAM radius = program.local[2]; PARAM half = { 0.5, 0.5, 0.5, 0.5 }; ATTRIB normal = vertex.normal; ATTRIB tangent = vertex.texcoord[1]; ATTRIB binormal = vertex.texcoord[2]; TEMP L, H, V, i; OUTPUT Tdecal = result.texcoord[0]; OUTPUT Lt = result.texcoord[1]; OUTPUT Ht = result.texcoord[2]; 1)Вычислить вектор источника света ADD L, light, -vertex.position; 2)Нормализировать его DP3 i, L, L; RSQ i.x, i.x; MUL L, L, i.x; MOV L.w, 1.0; 3)Трансформировать вектор источника света в пространство касательных. DP3 Lt.x, L, tangent; DP3 Lt.y, L, binormal; DP3 Lt.z, L, normal; MOV Lt.w, 1.0; 4)Вычислить вектор камеры ADD V, eye, -vertex.position; 5)Нормализировать его DP3 i, V, V; RSQ i.x, i.x; MUL V, V, i.x; MOV V.w, 1.0; 6)Просчитать H вектор (смотрите модели освещения Blinn`а; H half-angle vector) ADD H, L, V; то есть H=(L+V)*0.5 MUL H, H, half; 7)Трансформировать H вектор в пространство касательных. DP3 Ht.x, H, tangent; DP3 Ht.y, H, binormal; DP3 Ht.z, H, normal; MOV Ht.w, 1.0; MOV Tdecal, vertex.texcoord[0]; END Пиксельный шейдер: !!ARBfp1.0 PARAM color = program.local[0]; PARAM exponent = program.local[1]; PARAM diff = program.local[2]; PARAM spec = program.local[3]; PARAM values = { 0.5, 1, 2, 8 }; ATTRIB Tdecal = fragment.texcoord[0]; ATTRIB Lt = fragment.texcoord[1]; ATTRIB Ht = fragment.texcoord[2]; TEMP tmp, N, Ln, Hn, diffuse, specular, NdotL, NdotH, decal; 1) Нормализировать вектор источника света в пространстве касательных DP3 tmp, Lt, Lt; RSQ tmp.x, tmp.x; MUL Ln, Lt, tmp.x; 2) Нормализировать Н вектор в пространстве касательных DP3 tmp, Ht, Ht; RSQ tmp.x, tmp.x; MUL Hn, Ht, tmp.x; 3) Прочитать из normal текстуры и превести к норме по формуле перевода цвета в вектор TEX N, Tdecal, texture[1], 2D; MAD N, N, values.zzzz, -values.yyyy; 4) Просчитать dot product (скалярное произведение) вектора нормали из normal текстуры и вектора источника света в пространстве касательных DP3_SAT NdotL, N, Ln; 5) Просчитать dot product (скалярное произведение) вектора нормали из normal текстуры и Н вектора в пространстве касательных DP3_SAT NdotH, N, Hn; 6) Просчитать цвет с помощью diffuse (входного параметра) ADD_SAT NdotL, NdotL, diff; 7) Прочитать цвет из Diffuse текстуры TEX decal, Tdecal, texture[0], 2D; MUL_SAT diffuse, NdotL, decal; MUL_SAT diffuse, diffuse, color; 8) Просчитать Specular с учетом Shininess POW specular.x, NdotH.x, exponent.x; MUL_SAT specular, specular.xxxx, spec; 9) Просчитать финальный результат diffuse * specular в границах [0..1] ADD_SAT result.color, diffuse,specular; END Существует несколько модификаций классического normal mapping`а: - gloss mapping – когда specular читается из gloss текстуры. (регулирует степень отражения, очень полезно для имитации ржавчины) - parallax mapping – перекрывающийся бамп (Oblivion, Stalker). Добавляется карта высот и по ней делается зависимая выборка - horizont mapping – самозатеняющийся бамп - POM – самый красивый и самый тяжелый вариант. Подробности тут: www.ati.com/developer/i3d2006/I3D2006-Tatarchuk-POM.pdf Материалы и утилиты по данному вопросу: http://www.delphi3d.net/articles/viewarticle.php?article=bumpmapping.htm http://www.delphi3d.net/articles/viewarticle.php?article=phong.htm NVMeshMender в DXSDK или тут: http://download.developer.nvidia.com/developer/SDK/Individual_Samples/samples.html#MeshMenderSimpleExample
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
![]() |
![]() |
![]() |
Дизайн Elite Games V5 beta.18 EGM Elite Games Manager v5.17 02.05.2010 |
![]() |