HLFX.Ru Forum Страницы (2): [1] 2 »
Показать все 20 сообщений этой темы на одной странице

HLFX.Ru Forum (https://hlfx.ru/forum/index.php)
- OpenGL (https://hlfx.ru/forum/forumdisplay.php?forumid=7)
-- Эффект преломления как в Half-Life2 (https://hlfx.ru/forum/showthread.php?threadid=19)


Отправлено XaeroX 22-10-2005 в 08:37:

Эффект преломления как в Half-Life2

Эффект преломления

Преломление во многих разработках реализуется в вершинной программе на основе вектора нормали к данной вершине. Однако для этого требуется высокополигональная модель, иначе вершин (а значит, и нормалей) будет недостаточно для правильного преломления.
Сейчас повсеместно используются карты нормалей для детализации поверхностей. Недавно я приводил пример, как сделать высокодетализированный эффект хромированной поверхности с их помощью. Теперь рассмотрим эффект преломления.
Вспомните ребристые дверные стекла в Half-Life 2. Искажение мира за ними выглядит очень правдоподобно. Мы сделаем что-то очень похожее.
Для начала нам нужно захватить изображение мира в текстуру. Для этого я сделал один проход, выводящий изображение в квадрат 256 х 256. В принципе, можно было этого не делать и использовать расширение GL_NV_texture_rectangle, при этом нужно было бы изменить матрицу текстуры и заменить функции обращения к текстуре в шейдере.
Итак, мы отрендерили объекты мира в текстуру. Теперь нужно настроить матрицу текстуры для проецирования обычным способом и подключить вершинную и фрагментную программу.
Сама идея преломления заключается в следующем. Мы передаем нормаль к поверхности во фрагментную программу. Далее в ней мы получаем попиксельно нормали из карты нормалей и вычисляем их скалярное произведение. После этого мы просто умножаем координаты проекции на полученное значение. В случае, если обе нормали совпали (dot=1), сцена не искажается, иначе – искажается тем сильнее, чем больше отличие нормалей.
Вершинная программа делает вот что:
1. Вычисляет проекцию вершины.
2. Вычисляет координаты проекции для вершины.
3. Передает нормаль как координаты текстуры юнита 2.
4. Передает координаты текстуры юнита 0 и текущий цвет.

Cg Vertex Shader:
1
struct VertIn
2
{
3
  float4 pos : POSITION;
4
  float3 normal : NORMAL;
5
  float2 tex0 : TEXCOORD0;
6
  float4 color : COLOR;
7
};
8
 
9
struct VertOut
10
{
11
  float4 pos : POSITION;
12
  float2 tex0 : TEXCOORD0;
13
  float4 tex1 : TEXCOORD1;
14
  float3 norm : TEXCOORD2;
15
  float4 color : COLOR;
16
};
17
 
18
VertOut main(VertIn vin)
19
{
20
  VertOut vout;
21
  vout.pos = mul(glstate.matrix.mvp, vin.pos);
22
  vout.tex0 = vin.tex0;
23
  vout.tex1 = mul(glstate.matrix.texture[1], vin.pos);
24
  vout.norm = vin.normal;
25
  vout.color = vin.color;
26
  return vout;
27
}

Переходим к фрагментной программе. Для начала получаем нормаль и приводим ее к диапазону [-1,1], после чего вычисляем координаты преломления, как описано выше. W-компонент не трогаем, он используется для проецирования. Получаем цвета текстуры и проекции и усредняем их, домножив на текущий цвет.
Cg Pixel Shader:
1
struct VertOut
2
{
3
  float4 pos : POSITION;
4
  float2 tex0 : TEXCOORD0;
5
  float4 tex1 : TEXCOORD1;
6
  float3 norm : TEXCOORD2;
7
  float4 color : COLOR;
8
};
9
 
10
struct FragOut
11
{
12
  float4 col : COLOR;
13
};
14
 
15
FragOut main(VertOut fin,
16
uniform sampler2D diffuseMap :TEXUNIT0,
17
uniform sampler2D screenMap :TEXUNIT1,
18
uniform sampler2D normalMap :TEXUNIT2)
19
{
20
  FragOut fout;
21
 
22
  //get diffuse texture color
23
  float4 diffuse = tex2D(diffuseMap, fin.tex0);
24
 
25
  //get normal and expand it from [0,1] to [-1,1]
26
  float3 normal = tex2D(normalMap, fin.tex0).xyz;
27
  normal = normal*2 - 1;
28
 
29
  //compute refraction texcoords using difference btw normals, and lookup screen texture
30
  float4 refraction;
31
  refraction.xyz = fin.tex1.xyz * dot(normal, fin.norm);
32
  refraction.w = fin.tex1.w;
33
  float4 screen = tex2Dproj(screenMap, refraction);
34
 
35
  fout.col = fin.color * (diffuse + screen) * 0.5;
36
  return fout;
37
}

В примере слева вы увидите проекцию без преломления (это именно проекция, а не полупрозрачная поверхность!). Справа – шейдерное преломление. Кликайте мышью для смены карты нормалей. Жду ваших отзывов
P.S.: заранее отвечаю на вопрос, почему нет полных исходников. Я выложил код шейдеров, а это и есть само ноу-хау. Остается только их присоединить к проекту – это дело техники. Кроме того, этот эффект используется в Half-Life FX, а потому полные исходники не могут быть открыты до его релиза.

Для работы примера требуется поддержка вершинных и пиксельных шейдеров 2.0

__________________

xaerox on Vivino


Отправлено XaeroX 23-10-2005 в 09:12:

Что-то народ неактивно комментирует
Для тех, у кого вторые шейдеры не поддерживаются, вот пара скринов. Конечно, видеть это надо в динамике, но все же...


__________________

xaerox on Vivino


Отправлено Дядя Миша 24-10-2005 в 06:43:

XaeroX
Насколько я понимаю - рассчет преломления делается на основе самой текстурки и напрямую от нее зависит.
В хл2 рифленые стекла были вертикальными
Хорошая штука


Отправлено XaeroX 24-10-2005 в 07:04:

g-cont нарисуй "вертикальную" нормалмапу, в смысле полосы на ней вертикальные, и будет тебе щастье ;Р

__________________

xaerox on Vivino


Отправлено Security 24-10-2005 в 14:39:

Xaerox

Это для первой халвы???!!!


Отправлено Дядя Миша 24-10-2005 в 16:10:

XaeroX да я понимаю
Security да для первой.


Отправлено BUzer 25-10-2005 в 02:09:

Классно, только текстурку-бы получше подобрать..

Тутор, наверное, писался для таких дубов в этом деле, как я? Можно уж было тогда по-понятнее.. Вот, например, фраза
"1. Вычисляет проекцию вершины.
2. Вычисляет координаты проекции для вершины."
очень жуткая Я так понял, под первым подразумевается умножение на видовую матрицу, а под вторым - нахождение спроецированных текстурных координат для "экранной" текстуры?

Также не помешали-бы комментарии к переменным при описании структур - типа что в них будет храниться... По-русски

И наконец, вечно мучивший меня вопрос - а что, из пиксельного шейдера нельзя узнать цвет пикселя в цветовом буфере экрана? Если да, то это просто кидалово какое-то. А как тогда делать прозрачный полигон? (я так понимаю, в твоем примере он не прозрачен)


Отправлено XaeroX 25-10-2005 в 07:10:

BUzer
1. да, ты понял совершенно верно
2. гм... не люблю русские комментарии.
3. нельзя. зато прозначность можно задать умножением на fin.color.w - это и есть альфа фрагмента.

__________________

xaerox on Vivino


Отправлено BUzer 25-10-2005 в 10:16:

XaeroX
3. Не понял, умножением чего?.. Вот я хочу вывести полупрозрачный полигон с пикс шейдером. Мне надо будет испольховать glEnable(GL_BLEND), glBlendFunc..? И куда шейдер будет выдавать альфу?


Отправлено XaeroX 25-10-2005 в 10:20:

Цитата:
Автор XaeroX
fin.color.w - это и есть альфа фрагмента

Это в терминологии Cg. То есть это альфа входная (задаваемая через glColor4f). Альфу текстуры нужно учитывать самому. А обычная прозрачность будет выводиться так:
Cg Pixel Shader:
fout.col.w = fin.col.w;

С учетом альфа-канала текстуры:
Cg Pixel Shader:
float4 diffuse = tex2D(diffuseMap, fin.tex0);
// any code here...
fout.col.w = fin.col.w * diffuse.w;

__________________

xaerox on Vivino


Отправлено BUzer 25-10-2005 в 11:17:

А контролировать процесс смешивания расчитанного в шейдере цвета с цветом на экране можно только через glBlendFunc, получается?..


Отправлено XaeroX 25-10-2005 в 17:02:

glBlendFunc, как я понимаю, учитывается частично - для цвета имеющегося фрагмента. А цвет фрагмента наложения рассчитывается целиком в шейдере.

__________________

xaerox on Vivino


Отправлено FiEctro 25-08-2007 в 13:51:

Знаю что тема устарела ... Но у меня ламерский вопрос : Реализовывать в хл это все точно также как и func_mirror ? И как сделать что бы вместо нормалей читалась обычная WAD текстура с началом к примеру ( * ) ?

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Отправлено XaeroX 25-08-2007 в 17:05:

-CJ- как найти текстуру в ваднике по имени - есть в коде ксаша (там просматривается texinfo). Ну и потом биндишь ее, что-то типа glBindTexture(GL_TEXTURE_2D, msurface->texinfo->texture->gl_index);

__________________

xaerox on Vivino


Отправлено FiEctro 26-08-2007 в 11:49:

XaeroX спасибо ! Но в ксаше ( water.cpp ) я неособо разобрался какой код отвечает за наложение эфекта преломления и отражения на текстуру ( % )
И еще я не особо понял смысл закоментированого в ( water.cpp ) кода и коментов

code:
/* // This code should do the same on Gf4Ti (nv_texture_shader, nv_texture_shader2, nv_texture_shader3) // BUT IT DOESN'T!!!! // // NB: if you wanna test it, do the following in gl_mirrors.cpp // - operate the texture matrix for texture1 // - swap texcoords for units 0 and 1 void CreateWaterShader_ARB(void) { logPrint("Generating noise texture\n"); CreateNoiseTextureDsDt(1); logPrint("Completed\n"); } ....

__________________
У котёнка мокрый нос и гладенькая шерсть, у него забавный хвост и быстрых лапок шесть. Две задних, две средних и две передних лапы, такая многоножка получилася у папы.
Он ученый — папа мой — зверушек изучает, гуляет по помойкам, ловит крыс и чаек. Две крысы белокрылые и чайки две унылые покрытые пупырчатою кожей лягушат без пёрышек тоскуют и ускакать спешат.
А ещё есть муравей большой размером с гуся он пугает всех зверей, и я его боюся, когда он ковыляет на лапках на своих.
И в двери ударяет, и начинает стих: Я — муравей, воды налей! Не меньше ведра, напиться мне пора!


Временная зона GMT. Текущее время 01:56. Страницы (2): [1] 2 »
Показать все 20 сообщений этой темы на одной странице

На основе vBulletin версии 2.3.0
Авторское право © Jelsoft Enterprises Limited 2000 - 2002.
Дизайн и программирование: Crystice Softworks © 2005 - 2024