HLFX.Ru Forum
Показать все 14 сообщений этой темы на одной странице

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=140)


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

Цветовая аберрация в преломлениях

Если мы хотим сделать по-настоящему красивое преломление, нам нужно учитывать тот факт, что в природе белый свет состоит из лучей с разной длиной волны, и каждый отклоняется на разный угол при преломлении. Простой пример - призма, разлагающая белый свет на спектр. Мы попробуем смоделировать такие преломления.
Для начала рассмотрим обычное монохроматическое преломление. В первую очередь обратим внимание на тот факт, что в природе не бывает поверхностей, полностью пропускающих свет - часть его всегда отражается. То есть нам требуется рассчитать отраженный и преломленный векторы для каждой вершины, на основе которых мы получим координаты текстуры. Для этого есть стандартные библиотечные функции refract и reflect. Коэффициент преломления возьмем постоянным и равным 0.1:

Cg Vertex Shader:
1
struct VertIn
2
{
3
  float4 pos : POSITION;
4
  float4 normal : NORMAL;
5
  float2 tex0 : TEXCOORD0;
6
  float4 color : COLOR;
7
};
8
 
9
struct VertOut
10
{
11
  float4 pos : POSITION;
12
  float4 reflectVec : TEXCOORD0;
13
  float4 refractVec : TEXCOORD1;
14
  float4 fresnelTerm : COLOR;
15
};
16
 
17
// fresnel approximation
18
fixed fast_fresnel(float3 I, float3 N, float3 fresnelValues)
19
{
20
  fixed power = fresnelValues.x;
21
  fixed scale = fresnelValues.y;
22
  fixed bias = fresnelValues.z;
23
  return bias + pow(1.0 - dot(I, N), power) * scale;
24
}
25
 
26
VertOut main(VertIn vin)
27
{
28
  VertOut vout;
29
  vout.pos = mul(glstate.matrix.mvp, vin.pos);
30
 
31
  float3 eyeToVert = normalize(mul(glstate.matrix.modelview[0],vin.pos).xyz);
32
  float3 normal = normalize(mul(glstate.matrix.invtrans.modelview[0],vin.normal).xyz);
33
 
34
  float4 refractVec = float4(refract(eyeToVert, normal, 0.1), 1);
35
  float4 reflectVec = float4(reflect(eyeToVert, normal), 1);
36
 
37
  vout.reflectVec = mul(glstate.matrix.texture[0], reflectVec);
38
  vout.refractVec = mul(glstate.matrix.texture[1], refractVec);
39
 
40
  // calculate the fresnel reflection
41
  vout.fresnelTerm = fast_fresnel(-eyeToVert, normal, float3(5.0, 1.0, 0.0));
42
 
43
  return vout;
44
}

У нас есть два варианта: использовать кубические карты окружения или обычные 2D-текстуры, снимаемые с экрана. В первом случае не нужно дополнительное преобразование по матрицам текстуры, цель которого - убрать перспективное преобразование. Я выбрал второй способ. Итак, в пиксельном шейдере нам нужно получить цвет отражения и преломления и объединить их.
Cg Pixel Shader:
1
struct VertOut
2
{
3
  float4 pos : POSITION;
4
  float4 reflectVec : TEXCOORD0;
5
  float4 refractVec : TEXCOORD1;
6
  float4 fresnelTerm : COLOR;
7
};
8
 
9
struct FragOut
10
{
11
  float4 col : COLOR;
12
};
13
 
14
FragOut main(VertOut fin,
15
uniform sampler2D reflectMap : TEXUNIT0,
16
uniform sampler2D refractMap : TEXUNIT1)
17
{
18
  FragOut fout;
19
 
20
  float3 refractColor = tex2Dproj(refractMap, fin.refractVec).rgb;
21
  float3 reflectColor = tex2Dproj(reflectMap, fin.reflectVec).rgb;
22
  float3 reflectRefract = lerp(refractColor, reflectColor, fin.fresnelTerm.xyz);
23
 
24
  fout.col = float4(reflectRefract, 1.0);
25
  return fout;
26
}


Вот как это выглядит:


Теперь добавим эффект аберрации лучей. Все, что для этого требуется - рассчитать три разных вектора преломления (для красного, зеленого и синего компонента света) с разными коэффициентами преломления.
Cg Vertex Shader:
1
struct VertIn
2
{
3
  float4 pos : POSITION;
4
  float4 normal : NORMAL;
5
  float2 tex0 : TEXCOORD0;
6
  float4 color : COLOR;
7
};
8
 
9
struct VertOut
10
{
11
  float4 pos : POSITION;
12
  float4 reflectVec : TEXCOORD0;
13
  float4 refractVecR : TEXCOORD1;
14
  float4 refractVecG : TEXCOORD2;
15
  float4 refractVecB : TEXCOORD3;
16
  float4 fresnelTerm : COLOR;
17
};
18
 
19
// fresnel approximation
20
fixed fast_fresnel(float3 I, float3 N, float3 fresnelValues)
21
{
22
  fixed power = fresnelValues.x;
23
  fixed scale = fresnelValues.y;
24
  fixed bias = fresnelValues.z;
25
  return bias + pow(1.0 - dot(I, N), power) * scale;
26
}
27
 
28
VertOut main(VertIn vin)
29
{
30
  VertOut vout;
31
  vout.pos = mul(glstate.matrix.mvp, vin.pos);
32
 
33
  float3 eyeToVert = normalize(mul(glstate.matrix.modelview[0],vin.pos).xyz);
34
  float3 normal = normalize(mul(glstate.matrix.invtrans.modelview[0],vin.normal).xyz);
35
 
36
  float4 reflectVec = float4(reflect(eyeToVert, normal), 1);
37
  float4 refractVecR = float4(refract(eyeToVert, normal, 0.15), 1);
38
  float4 refractVecG = float4(refract(eyeToVert, normal, 0.10), 1);
39
  float4 refractVecB = float4(refract(eyeToVert, normal, 0.05), 1);
40
 
41
  vout.reflectVec = mul(glstate.matrix.texture[0], reflectVec);
42
  vout.refractVecR = mul(glstate.matrix.texture[1], refractVecR);
43
  vout.refractVecG = mul(glstate.matrix.texture[1], refractVecG);
44
  vout.refractVecB = mul(glstate.matrix.texture[1], refractVecB);
45
 
46
  // calculate the fresnel reflection
47
  vout.fresnelTerm = fast_fresnel(-eyeToVert, normal, float3(5.0, 1.0, 0.0));
48
  return vout;
49
}

В пиксельном шейдере нам нужно взять соответствующие цветовые компоненты по векторам преломления в экранной текстуре, и объединить их в один цвет преломления. А далее все так же - объединяем его с цветом отражения.
Cg Pixel Shader:
1
struct VertOut
2
{
3
  float4 pos : POSITION;
4
  float4 reflectVec : TEXCOORD0;
5
  float4 refractVecR : TEXCOORD1;
6
  float4 refractVecG : TEXCOORD2;
7
  float4 refractVecB : TEXCOORD3;
8
  float4 fresnelTerm : COLOR;
9
};
10
 
11
struct FragOut
12
{
13
  float4 col : COLOR;
14
};
15
 
16
FragOut main(VertOut fin,
17
uniform sampler2D reflectMap : TEXUNIT0,
18
uniform sampler2D refractMap : TEXUNIT1)
19
{
20
  FragOut fout;
21
 
22
  float3 refractColor;
23
  refractColor.r = tex2Dproj(refractMap, fin.refractVecR).r;
24
  refractColor.g = tex2Dproj(refractMap, fin.refractVecG).g;
25
  refractColor.b = tex2Dproj(refractMap, fin.refractVecB).b;
26
 
27
  float3 reflectColor = tex2Dproj(reflectMap, fin.reflectVec).rgb;
28
  float3 reflectRefract = lerp(refractColor, reflectColor, fin.fresnelTerm.xyz);
29
 
30
  fout.col = float4(reflectRefract, 1.0);
31
  return fout;
32
}

Получаем вот такой симпатичный эффект. Для карты отражения я использовал ту же текстуру, что и для карты преломления, но вы можете использовать свою, или кубическую карту (как уже говорилось выше). Можно также использовать карты нормалей для более детализированной геометрии, но это сильно нагрузит пиксельный шейдер, т.к. операции по рассчету преломлений и отражений придется делать в нем.


В примере нажмите пробел для включения и выключения аберрации. Само собой, требуется поддержка вторых шейдеров.

__________________

xaerox on Vivino


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

Само преломление рулит, правда я не понял прикола с цветовой абберацией.. Ну добавляется какая-то красная подсветка.. В роли игрока, мне было-бы пофигу


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

BUzer ты запусти пару мыльных пузырей и посморти Там идет разложение света на спектр при преломлении. Я конечно не ручаюсь, что мой вариант суперреалистичен, но что-то похожее имитирует.

__________________

xaerox on Vivino


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

Ну вот может на чайнике лучше видно, что дает аберрация

__________________

xaerox on Vivino


Отправлено Security 10-12-2005 в 10:57:

XaeroX, а в чём прикол? В отражении справа на лево?


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

Security специально для тебя - ЛОПАТА!

__________________

xaerox on Vivino


Отправлено Security 10-12-2005 в 11:38:

Понял. От меня тебе - СТРУЧОК!


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

А, не... Правильнее сказать: РАДЕОН
только вот хз почему

__________________

xaerox on Vivino


Отправлено Security 10-12-2005 в 11:50:

Вот и я ничего не понял.


Отправлено Ku2zoff 06-05-2007 в 10:22:

Мне кажется, на радеонах мало что нормально пашет. У меня например нету теней в хлфх. И вообще у меня хлфх вылетает, когда подбираешь оружие или батарейку. Когда клиента заменяешь на клиента обычной халфы - всё работает


Отправлено Skaarj 06-05-2007 в 13:34:

Понравилось, играюсь подставляя различные картинки.

Добавлено сегодня в 15:00:

Вот только если взять шар, то в центре хроматической абберации быть не должно, там свет никак не переломляется, а у тебя всё равномерено разложенно по цветам вне зависимости от улов переломленя.

Добавлено сегодня в 16:34:

Ещё раз глянул, всё ок, по центру аберрации нету.


Отправлено Alerman 07-05-2007 в 03:58:

Цитата:
Ku2zoff писал:
Когда клиента заменяешь на клиента обычной халфы - всё работает
Хм... может и мне попробовать...

__________________
Я за Ленина, за мир и за СССР, НО я против сталина, против тех кто "наводит мир" силой, и против Кремля!


Отправлено FiEctro 28-05-2007 в 18:41:

Ku2zoff
>> Когда клиента заменяешь на клиента обычной халфы - всё работает

Странно , по теории если заменить клиентку мода на стандартную , то новшества врятли будут работать , если только они не на сервере

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


Отправлено WoRKER 05-07-2007 в 15:37:

Эй!

А можно что-то фееричное?

__________________
Boom.
Скоро на Ваших мониторах.


Временная зона GMT. Текущее время 16:51.
Показать все 14 сообщений этой темы на одной странице

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