forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Проекты C++ (http://forum.boolean.name/forumdisplay.php?f=56)
-   -   Статья:Parallax Mapping (http://forum.boolean.name/showthread.php?t=8520)

Genius 21.06.2009 03:01

Статья:Parallax Mapping
 
Вобщем я раскажу как сделать Parallax Mapping технику на языке HLSL(High Level Shader Language).

Для начала,что такое Parallax Mapping? Parallax Mapping это техника нам позваляет сделать из простого плоского полигона имитацию высоко полигональной модели.

Пример Normal Mapping:

Пример Parallax Mapping:


Для постраения этой самой "высоко полигональной модели" необхадима Height мапа,которую мы можем получить с помощью таких тулзов как CrazyBump,3dsMax,Maya.
Выглидит она вот таким образом:



И так,начнём наш шейдер:

Код:

float4x4 World : WORLD; // Мировая матрица трансформации модели
float4x4 View  : VIEW; // Видовая матрица
float4x4 Proj  : PROJECTION; // Матрица проекции

// Input стрктура вершиного шейдера
struct VS_INPUT
{
  float3 position : POSITION0; // Не трансформированая позиция вершины
  float3 normal  : NORMAL0; // Нормаль вершины
  float2 texcoord : TEXCOORD0; // Текстурные координаты
  float3 tangent  : TANGENT0; // Тангент вершины
  float3 binormal : BINORMAL0; // Би-нормаль вершины
};

// Оутпат структура вершиного шейдера
struct VS_OUTPUT
{
    float4 position : POSITION0; // Трансформированая позиция вершины
    float2 texcoord : TEXCOORD0; // Текстурные координаты : Для Pixel-Shader
    float3 normal  : TEXCOORD2;  // Нормаль : Для Pixel-Shader
    float3 tangent  : TEXCOORD3; // Тангент : Для Pixel-Shader
    float3 binormal : TEXCOORD4; // Би-нормаль : Для Pixel-Shader
    float3 position2: TEXCOORD5; // Мировая позиция вершины : Для Pixel-Shader
};

// Вершиный шейдер:
VS_OUTPUT vs_main(VS_INPUT In)
{
    VS_OUTPUT Out = (VS_OUTPUT)0;
    Out.position = mul(In.position,World); /* домножаем позицию вершины на
    мировую матрицу трансформации
    */
    Out.position2 = Out.position; // Сохраняем её так-как она нам ещё понадобится
    Out.position = mul(mul(Out.position,View),Proj); /* Домнажаем позицию
    на матрицу вида и проекции*/
    Out.normal = normalize(mul(In.normal,World)); /* Доманажаем нормаль на
    мировую матрицу и нормализуем */
    Out.tangent = normalize(mul(In.tangent,World)); /* Доманажаем тангент на
    мировую матрицу и нормализуем */
    Out.binormal = normalize(mul(In.binormal,World)); /* Доманажаем би-нормаль на
    мировую матрицу и нормализуем */
    Out.texcoord = In.texcoord; // сохраняем текстурные координаты
    return Out; // Finish :)
}

float3 cameraPos; // позиция камеры
float3 lightPos; // позиция источника
float lightRadius; // радиус источника
sampler DiffuseMap : register(s0); //фиксируем семплер дефьюзной карты на 0 слот
sampler NormalMap : register(s1); //фиксируем семплер нормаль карты на 1 слот
sampler HeightMap : register(s2); //фиксируем семплер карты высот на 2 слот
float parallaxIntensity = 0.05f; /* интенсивность паралакса,
больше ставить не советую :-) ,разве что поменьше. */


// Пиксельный шейдер
float4 ps_main(VS_OUTPUT In) : COLOR0
{
      float4 Out = 0;
      float heightValue = tex2D(HeightMap,In.texcoord).r; // Получаем height виличину текущего пикселя
      float2 offsetCoord=In.texcoord;
     
      float3x3 tbn; // Трёх мерная матрица Tangent Space
      tbn[2] = In.normal;
      tbn[0] = In.tangent;
      tbn[1] = In.binormal;
     
      float3 viewVec = normalize(mul(cameraPos - In.position2.xyz,tbn)); /* получаем видовой вектор ,
      по не замысловатой формуле (Camera Position  - World Position) * TangetSpace ,
      и нормализуем его */

      float2 parallaxSize = parallaxIntensity * float2(2, -1);
      offsetCoord += viewVec.xy * (heightValue * parallaxSize.x + parallaxSize.y);// получаем новые текстурные координаты
   
    /* так всё мы имеем нужные нам новые текстурные координаты
    далле всё как в простом нормал меппинге только выборки
    делаем по новым текстурным координатам!*/


      float4 color = tex2D(DiffuseMap,offsetCoord); // цвет
      float3 normal = tex2D(NormalMap,offsetCoord).xyz * 2 - 1; // компенсирующая нормаль
      normal = normalize(mul(normal,tbn)); // переводим её в Tangent Space
   
      float3 lightAng = normalize(lightPos - In.position2.xyz); /* вычисляем позицию
      источника света отнасительно мировой позиции вершины*/
      float atten  = saturate(1.0f - distance(In.position2.xyz, lightPos) / lightRadius); // аттенуация источника(затухание)
      float3 NdL = saturate(dot(lightAng,normal));  // Dot product векторов lightAng,normal
     
      Out = color * NdL * atten; Финальный цвет пикселя

      return Out; // Finish :-)
}

Фух,вроде всё учёл,если нет,то я старался учесть :-) .
На последок скажу,что Parallax Mapping не единственная техника в своём роде,есть ещё и расширения типа Step Parallax Mapping,Parallax Occlusion Mapping и д.р.
Спасибо за внимание! И до новых встреч!:-)
Матереалы по Parallax Mapping расширениям:
- Step Parallax Mapping http://graphics.cs.brown.edu/games/S...lax/index.html
- Parallax Occlusion Mapping - Можно посмотреть либо в Direct3D SDK,либо в AMD Render Monkey, http://ati.amd.com/developer/kri06/K...archuk-POM.pdf.
- Relief Mapping http://developer.download.nvidia.com...gems3_ch18.pdf
- Parallax Mapping Steps3D http://steps3d.narod.ru/tutorials/pa...-tutorial.html
Так же:
- HLSL http://ru.wikipedia.org/wiki/HLSL

Genius 21.06.2009 03:03

Ответ: Статья:Parallax Mapping
 
Похоже немного разделом ошибся:@

ffinder 21.06.2009 12:40

Ответ: Статья:Parallax Mapping
 
все здорово, но вот принцип лежащий в основе описал бы, чтобы не копипаст люди делали, а могли поправить/изменить при случае

ABTOMAT 21.06.2009 14:14

Ответ: Статья:Parallax Mapping
 
Цитата:

все здорово, но вот принцип лежащий в основе описал бы, чтобы не копипаст люди делали, а могли поправить/изменить при случае
И правда, хотелось бы подробностей. Ну а так впечатляет.
Похоже, у МоКи есть достойные последователи.

Mr_F_ 21.06.2009 15:06

Ответ: Статья:Parallax Mapping
 
Цитата:

Parallax Mapping это техника нам позваляет сделать из простого плоского полигона имитацию высоко полигональной модели.
некорректно, он просто делает иллюзию выдавливания по хейт мапе.

Genius 21.06.2009 15:27

Ответ: Статья:Parallax Mapping
 
Ну как видите,что то не учёл,следующий раз обязательно учту :),сегодня\завтро думаю написать про Parallax Occlusion Mapping.

Taugeshtu 21.06.2009 17:53

Ответ: Статья:Parallax Mapping
 
Лучше этот семпл дополни описанием принципов работы прежде чем за новый браться... А то будет куча объедков, и никакого понимания вопроса у новичков вроде меня...

Genius 21.06.2009 18:02

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от Ize'g0re (Сообщение 108524)
Лучше этот семпл дополни описанием принципов работы прежде чем за новый браться... А то будет куча объедков, и никакого понимания вопроса у новичков вроде меня...

А что конкретно не понятно? Я просто не знаю же,а так буду знать и исправлю.

NitE 21.06.2009 18:05

Ответ: Статья:Parallax Mapping
 
да нече не понятно, ты должен каждый шаг расписывать очень подробно, а не одной строчкой комментария, посмотри как другие статьи пишут...

jimon 21.06.2009 18:10

Ответ: Статья:Parallax Mapping
 
Genius
распиши как тут http://steps3d.narod.ru/tutorials/pa...-tutorial.html , тогда некоторые поймут
но для хорошей статьи надо еще подробнее разжевать

Genius 21.06.2009 18:46

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от jimon (Сообщение 108531)
Genius
распиши как тут http://steps3d.narod.ru/tutorials/pa...-tutorial.html , тогда некоторые поймут
но для хорошей статьи надо еще подробнее разжевать

Я расписал на доступном языке,но вот эту ссылку для тех кто хочет вникнуть добавлю.


Да и в большенстве случаеш новички меньше читают,больше копипастят.

З.Ы. Немного привёл в порядок статью.

NitE 21.06.2009 18:54

Ответ: Статья:Parallax Mapping
 
Цитата:

Да и в большенстве случаеш новички меньше читают,больше копипастят.
с чего такой вывод ?

Genius 21.06.2009 18:55

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от NitE (Сообщение 108535)
с чего такой вывод ?

Сам так делал раньше...

NitE 21.06.2009 18:57

Ответ: Статья:Parallax Mapping
 
тогда пиши "да и в большенстве случаев я меньше читал, больше копипастил"

Taugeshtu 21.06.2009 19:44

Ответ: Статья:Parallax Mapping
 
Ты >< все новички.
Я не считаю себя новичком в блитце, но в шейдерах я новичок. Несмотря на это, я стремлюсь разобраться, а не скопипастить чужой шейдер "лишь бы работало".

Цитата:

Я расписал на доступном языке
Fail. Объясни мне пожалуйста поподробнее вот это:

Код:

Out.position = mul(In.position,World); /* домножаем позицию вершины на
    мировую матрицу трансформации
    */
    Out.position2 = Out.position; // Сохраняем её так-как она нам ещё понадобится
    Out.position = mul(mul(Out.position,View),Proj); /* Домнажаем позицию
    на матрицу вида и проекции*/
    Out.normal = normalize(mul(In.normal,World)); /* Доманажаем нормаль на
    мировую матрицу и нормализуем */
    Out.tangent = normalize(mul(In.tangent,World)); /* Доманажаем тангент на
    мировую матрицу и нормализуем */
    Out.binormal = normalize(mul(In.binormal,World)); /* Доманажаем би-нормаль на
    мировую матрицу и нормализуем */
    Out.texcoord = In.texcoord; // сохраняем текстурные координаты
    return Out; // Finish :)

Вот я не понимаю, для чего нужны все эти домножения, я не вижу цельной картины. Вообще ничего не понимаю, что откуда и куда приходит, и главное - зачем.
Считай, что ты ничего не объяснил, просто выложил код шейдера с незначительными комментариями. Объясни пожалуйста лично мне принцип, каким образом это делается? Пока ты не решишь эту задачу - не заслужишь моего "спасибо" а заодно оправдания слова "Статья" в заголовке темы.

Genius 21.06.2009 20:05

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от Ize'g0re (Сообщение 108540)
Ты >< все новички.
Я не считаю себя новичком в блитце, но в шейдерах я новичок. Несмотря на это, я стремлюсь разобраться, а не скопипастить чужой шейдер "лишь бы работало".


Fail. Объясни мне пожалуйста поподробнее вот это:

Код:

Out.position = mul(In.position,World); /* домножаем позицию вершины на
    мировую матрицу трансформации
    */
    Out.position2 = Out.position; // Сохраняем её так-как она нам ещё понадобится
    Out.position = mul(mul(Out.position,View),Proj); /* Домнажаем позицию
    на матрицу вида и проекции*/
    Out.normal = normalize(mul(In.normal,World)); /* Доманажаем нормаль на
    мировую матрицу и нормализуем */
    Out.tangent = normalize(mul(In.tangent,World)); /* Доманажаем тангент на
    мировую матрицу и нормализуем */
    Out.binormal = normalize(mul(In.binormal,World)); /* Доманажаем би-нормаль на
    мировую матрицу и нормализуем */
    Out.texcoord = In.texcoord; // сохраняем текстурные координаты
    return Out; // Finish :)

Вот я не понимаю, для чего нужны все эти домножения, я не вижу цельной картины. Вообще ничего не понимаю, что откуда и куда приходит, и главное - зачем.
Считай, что ты ничего не объяснил, просто выложил код шейдера с незначительными комментариями. Объясни пожалуйста лично мне принцип, каким образом это делается? Пока ты не решишь эту задачу - не заслужишь моего "спасибо" а заодно оправдания слова "Статья" в заголовке темы.

Это уже не относится к тематике данной статьи,и не к кокой из статей про имено графические эффекты,это уже чисто 3Д графика.

З.Ы. Писал не ради твоего спасибо,писал от душы.

moka 21.06.2009 20:35

Ответ: Статья:Parallax Mapping
 
Поработай над стилем написания кода - это очень важный моммент. Удвоит читабельность.
Думай над переменными и колличеством кода. У тебя слишком много мусора.
Длинные комменты в шейдере для каждой строки, без подсветки синтаксиса очень забивают весь шейдер лишними символами - читабельность падает.
Это не только параллакс. Если ты хочешь показать параллакс, и бамп, то распиши отдельно каждую технику, и затем опиши как соединял.
Если ющаешь входную и выходную структуры, то юзай их нормально:
void vs_main( in VS_INPUT IN, out _OUTPUT OUT ) {
Потом меняй переменные, а то видно куски из других шейдеров и разные стили кодеров.
Т.к. в шейдере одна вершинная и пиксельная функции, то юзай простые имена структур, такие как sv, sp (Structure Vertex, Structure Pixel).
Имена функций также простые - fv, fp.
void fv( in sv IN, sp OUT ) {

Уделяй стилю наивысший приоритет. По опыту скажу - это меняет абсолютно дело, только от этого в основном зависит как читатель вникнет, или мельком пробежавшись испугается, и бросит.
Шейдер ужастный. Если ты пишешь статью, то не выкладывай вот-вот написанный шейдер, а поработай над ним.
Статья плохая, тема хорошая.

jimon 21.06.2009 20:37

Ответ: Статья:Parallax Mapping
 
Код:

Out.normal = normalize(mul(In.normal,World)); /* Доманажаем нормаль на
    мировую матрицу и нормализуем */

кстати, с каких пор это правильно ? нормали умножают на специальную матрицу
потому что если у тебя будет нормаль к примеру (0,1,0), а на экране она должна быть (0,0.7,0.7), а мировая матрица содержит смещение и сделает из неё (1,1.7,1.7) то после нормализации ты получишь совсем не то что нужно

это написано и сдесь http://msdn.microsoft.com/en-us/library/bb172390.aspx

Genius 21.06.2009 20:40

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от MoKa (Сообщение 108544)
Уделяй стилю наивысший приоритет. По опыту скажу - это меняет абсолютно дело, только от этого в основном зависит как читатель вникнет, или мельком пробежавшись испугается, и бросит.
Шейдер ужастный. Если ты пишешь статью, то не выкладывай вот-вот написанный шейдер, а поработай над ним.
Статья плохая, тема хорошая.

Ну уж извените у меня другой стиль написания кода! :)

Цитата:

Сообщение от MoKa (Сообщение 108544)
Потом меняй переменные, а то видно куски из других шейдеров и разные стили кодеров.

:4to: ну вот ни разу,писал с нуля шейдер для статьи,сначало хотел просто взять из своего движка...

Genius 21.06.2009 20:42

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от jimon (Сообщение 108545)
[code]
это написано и сдесь http://msdn.microsoft.com/en-us/library/bb172390.aspx

Цитата:Camera Space Transformations

У меня World-Space.

jimon 21.06.2009 20:47

Ответ: Статья:Parallax Mapping
 
Genius
ну и что ? ты читал что я писал ? мне вот интересно к какому виду d3d приводит нормаль при умножении на матрицу, к x,y,z,1 или к x,y,z,0
если x,y,z,0 то будет работать, если первое - то нет

Genius 21.06.2009 20:50

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от jimon (Сообщение 108549)
Genius
ну и что ? ты читал что я писал ? мне вот интересно к какому виду d3d приводит нормаль при умножении на матрицу, к x,y,z,1 или к x,y,z,0
если x,y,z,0 то будет работать, если первое - то нет

x,y,z,0

moka 22.06.2009 03:43

Ответ: Статья:Parallax Mapping
 
Цитата:

Сообщение от Genius (Сообщение 108547)
Ну уж извените у меня другой стиль написания кода! :)

Дело в том что он для тебя может удобен. С моей точки зрения он никак не подходит для публики. Не припирайся, а задумайся, я говна не посоветую. Да есть многие кому нормально и так, есть многие кто прошёл мимо, есть многие кому пришлось ковыряться. Так вот недовольства можно уменьшить. Фишка в том что ты пишешь один, а читает многие. И чем ценее твоё время, чем время всех тех других? Если уловил о чём я, то приоритеты статьям поставишь выше. Статей дерьма в интернете куча, и по этой теме их тоже уйма. А вот нормальных и дружелюбных, любого рода статей очень мало. Но если они есть, то они на высоте у читателей. И они экономят время читателя, предостовляя всю нужную информацию и удобства.

Цитата:

Сообщение от Genius (Сообщение 108547)
:4to: ну вот ни разу,писал с нуля шейдер для статьи,сначало хотел просто взять из своего движка...

Куча стандартных имён. Использование разных привязок структур к функции, входящая объявляется заголовке функции, а выходящая внутри, это самая распространённая ещё одна загвоздка которая тратит ещё 3 строчки кода.
Шейдер - это не гипер исходник. Это мини программа. Мини - значит маленькая.

ABTOMAT 22.06.2009 04:06

Ответ: Статья:Parallax Mapping
 
MoKa, эдак ты отобьёшь желание писать общественно-полезные статьи.
Лучше покажи "как надо" :) Уверен, твой опыт многим пригодится. Хотя, понимаю: времени у нас у всех мало, но всё же статься оказалась бы незаменимой...

Mr_F_ 22.06.2009 11:19

Ответ: Статья:Parallax Mapping
 
Цитата:

Out.normal = normalize(mul(In.normal,World))
всё прально тут

moka 24.06.2009 01:28

Ответ: Статья:Parallax Mapping
 
ещё моммент такой, если нормализировать в вершинке, то у тебя будет повершинное освещение.
Сделай простой биллбоард, большой, поставь по серединке источник, и увидешь что он не подействует на пиксели. А только на вершинны как таковой.
А если будешь нормализовать в пиксельном будет ок.

Как-то наткнулся на это, вроде с этим и связано было..


Часовой пояс GMT +4, время: 10:01.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Перевод: zCarot