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=10)
Отправлено XaeroX 17-10-2005 в 09:57:
Совершенствуем "эффект хромирования"
В Half-Life, как вы наверное знаете, определенные текстуры на моделях выглядят как бы хромированными - их текстурные координаты искажаются определенным образом. Фактически для искажения нужны: вектора, задающие направления (вправо и вверх) и нормаль к вершине. Нормаль вычисляется для каждой вершины при подготовке модели, и полученные значения хрома умножаются на текущие координаты текстуры.
Смоделируем этот процесс. Для этого мы напишем вершинную программу, производящую нужные вычисления, а нормаль передаем средствами OpenGL (для боксов в примере нормали генерируются автоматически).
Cg Vertex Shader:
4 | float3 normal : NORMAL; |
5 | float3 tex0 : TEXCOORD0; |
11 | float4 pos : POSITION; |
12 | float4 tex0 : TEXCOORD0; |
16 | VertOut main(VertIn vin) |
19 | float4 g_vecRight = float4( 1.0f, 0.0f, 0.0f, 0.0f ); |
20 | float4 g_vecUp = float4( 0.0f, 1.0f, 0.0f, 0.0f ); |
22 | vout.pos = mul(glstate.matrix.mvp, vin.pos); |
23 | g_vecRight = mul(glstate.matrix.inverse.mvp, g_vecRight); |
24 | g_vecUp = mul(glstate.matrix.inverse.mvp, g_vecUp); |
26 | vout.tex0.x = vin.tex0.x * (dot(vin.normal, g_vecRight.xyz) + 1.0); |
27 | vout.tex0.y = vin.tex0.y * (dot(vin.normal, g_vecUp.xyz) + 1.0); |
Выглядит не очень красиво. Для более реалистичного эффекта нужно учесть микрорельеф поверхности попиксельно. Основные вычисления мы производим в пиксельной программе, а вершинная передает ей вектора направления (учтите: в вашей собственной игре нужно передавать вектора вручную, а не задавать как константы в шейдере!).
Вершинная программа выглядит просто:
Cg Vertex Shader:
4 | float3 normal : NORMAL; |
5 | float2 tex0 : TEXCOORD0; |
11 | float4 pos : POSITION; |
12 | float2 tex0 : TEXCOORD0; |
13 | float3 tex1 : TEXCOORD1; |
14 | float3 tex2 : TEXCOORD2; |
18 | VertOut main(VertIn vin) |
21 | float4 g_vecRight = float4( 1.0f, 0.0f, 0.0f, 0.0f ); |
22 | float4 g_vecUp = float4( 0.0f, 1.0f, 0.0f, 0.0f ); |
24 | vout.pos = mul(glstate.matrix.mvp, vin.pos); |
25 | vout.tex1 = mul(glstate.matrix.inverse.mvp, g_vecRight).xyz; |
26 | vout.tex2 = mul(glstate.matrix.inverse.mvp, g_vecUp).xyz; |
28 | vout.color = vin.color; |
Пиксельный шейдер чуть сложнее - нам вначале нужно прочитать нормаль из тектуры - карты нормалей (мы привязали ее к юниту 1).
Cg Pixel Shader:
4 | float2 tex0 : TEXCOORD0; |
5 | float3 tex1 : TEXCOORD1; |
6 | float3 tex2 : TEXCOORD2; |
15 | FragOut main(VertOut fin, |
16 | uniform sampler2D diffuseMap :TEXUNIT0, |
17 | uniform sampler2D normalMap :TEXUNIT1) |
22 | float4 normal = tex2D(normalMap, fin.tex0); |
24 | //expand normal [0,1] -> [-1,1] |
25 | normal.xyz = normal.xyz*2 - 1; |
27 | tc.x = fin.tex0.x * (dot(normal.xyz, fin.tex1.xyz) + 1.0); |
28 | tc.y = fin.tex0.y * (dot(normal.xyz, fin.tex2.xyz) + 1.0); |
30 | fout.col = fin.color * tex2D(diffuseMap, tc); |
Сравните два бокса в примере (справа - тот, что использует попиксельные нормали) и почувствуйте, так сказать, разницу!
Нажатием кнопки мыши можно изменить используемый нормалмап. По умолчанию используется "пустой" нормалмап - фактически простая нормаль, поэтому картинка справа идентична левой.
Пример требует наличия поддержки вершинных и пиксельных шейдеров 2.0__________________
Отправлено Format.com 17-10-2005 в 12:04:
Вложение - unexpected end of archive.
Отправлено XaeroX 17-10-2005 в 19:24:
Так, с аттачами вроде все исправил. Вот вложение. Кстати, я там изменил кое-что в шейдерах, теперь все правильнее.
__________________
Отправлено Дядя Миша 17-10-2005 в 19:33:
Хороший хром 
особенно 3 и 4 варианты.
Кстати тебе совет - сделай так, чтобы окошко нельзя было растягивать на весь экран, а то кубик пропадает.
Отправлено XaeroX 17-10-2005 в 19:36:
Окошко растягивать можно, но так, чтобы пропорции соблюдались. Так что больше можно сделать при желании.
Вот я когда-то про такой хром и говорил на Half-Life.ru. Его можно без проблем сделать на world brush'ах в хл. Чем я вскоре и займусь 
__________________
Отправлено Дядя Миша 17-10-2005 в 19:38:
XaeroX а нафига нужны хромированные браши? :confused:
Отправлено XaeroX 17-10-2005 в 19:43:
Ну как нафига. Металлические конструкции. И потом, хром ведь можно накладывать как вторую текстуру. Красиво смотрится - сам же сказал 
__________________
Отправлено BUzer 18-10-2005 в 10:47:
Красиво. А что исходник не приложил? 
Вот тоже че-нить подобное заиметь.. Кстати, а если не юзать cg, то под какое расширение лучше шейдер писать? arb_vertex_program? Или nv_ какой-нибудь?..
Отправлено XaeroX 18-10-2005 в 10:54:
Я сг для примера написал (кстати, это и есть исходник. дело в шейдере, остальное любой сам допишет). Я арб юзаю, и тебе советую, если хочешь, чтобы на радеонах работало.
__________________
Отправлено Дядя Миша 18-10-2005 в 11:14:
XaeroXвроде как бампом?
ну разве что так 
просто я лично считаю, что важны не сами эффекты, а их гармонирование с окружающей средой.
как пример - мощнейщая детализация на ящике с убогой текстуркой 32х32 дает прямо противоположные впечатления.
Отправлено XaeroX 18-10-2005 в 11:36:
g-cont согласен. но в примере текстурки 64 х 64, и вроде ничего так смотрятся. А бамп здесь не при чем, разве что карта нормалей тоже используется, а по сути все разное.
__________________
Отправлено Jumpdaphuckup! 12-11-2005 в 09:49:
XaeroX а ты бы сделал вариант только с вертексными шейдерами
Отправлено XaeroX 12-11-2005 в 09:54:
Цитата:
Jumpdaphuckup! писал:
а ты бы сделал вариант только с вертексными шейдерами
как ты себе это представляешь? 
__________________
Отправлено Jumpdaphuckup! 12-11-2005 в 14:49:
XaeroX если б представлял, то не просил бы
Отправлено XaeroX 12-11-2005 в 15:00:
Jumpdaphuckup! вся идея основана именно на пиксельных шейдерах
А вариант только на вертексных я там привел - смотри пример.
__________________