|
Bump mapping |
Bump mapping это наложение рельефа(неровностей) на участок поверхности. Для этого используется две текстуры одна для участка поверхности назовём её базовой, а другая для карты нормалей имитирующие неровности. Нормали учитывая угол освещения создают иллюзию неровной поверхности. Поэтому базовая текстура должна быть сопоставлена, с картой нормалей.
= |
* |
|||
TextureBump | TextureBase | NormalMap |
Если поворачивать полигон, то его собственные нормали будут также изменять направление, а значит источник должен это учесть. Ведь повернув полигон мы не поворачиваем вектор источника, соответственно у нас есть проблема. Решить её можно с помощью матрицы tangent – spase(TBN) которая трансформит источник относительно полигона. TBN представляет собой базис взаимно перпендикулярных векторов отдельно взятого полигона. Этот базис вычисляется один раз до вывода.
Для каждой поверхности мы имеем два базиса: texture space содержащий текстурные координаты и object space хранящий координаты полигона, источника освещения. Чтобы источник правильно светил на повёрнутый полигон его нужно преобразовать из object space в texture space.
Пусть object space использует базис [(1,0,0), (0,1,0), (0,0,1)], а texture space - [T, B, N] где N = [T x B]. Нам остаётся вычислить Т и В.
Пусть V4 некая точка лежащая внутрях полигона, С4 соответствующая ей текстурная координата. Разложим вектор (С4 – С1) по компонентам Т и В:
Т = (С4 – С1)T
В = (С4 – С1)B
Как я понял текстурные координаты участка (V4 - V1) есть сумма компонентов Т и В:
V4 - V1 = (C4 - C1)T * T + (C4 - C1)B * BСледовательно для двух сторон поверхности получаем систему уравнений с двумя неизвестными Т и В:
V2 - V1 = (C2 - C1)T * T + (C2 - C1)B * BЗапишем её в матричном виде
Чтобы в матричном уравнении [B] = [A] [X] найти [X], понадобится обратная матрица [A] -1 для умножения на обе части уравнения.
[A] -1 [B] = [A] [A] -1 [X]
т.к. [A] [A] -1 есть единичная матрица, зн
[A] -1 [B] = [X]
если [A] = | тогда [A] -1 = | определитель матрицы равен det(A) = t1 * b1 - t2 * b1. |
Очевидно det(A) не должен быть равен 0. Т.о. | ну и как было ранее сказано N = [T x B] |
А для вычисления вектора освещения нужно TBN умножить на world space
struct VS_IN { float4 position : POSITION; float2 texcoord : TEXCOORD0; // Заранее вычисленный tangent space float3 T : TANGENT; float3 B : BINORMAL; float3 N : NORMAL; // N = [T x B] }; struct VS_OUT { float4 position : POSITION; float2 texcoord : TEXCOORD0; float4 light : TEXCOORD1; // освещение учитанное tangent space - ом }; float4x4 WorldViewProj; float4x4 WorldView; float4 vLight;// освещение в object space VS_OUT main_vs_hlsl( VS_IN IN) { VS_OUT OUT; OUT.position = mul( IN.position, WorldViewProj ); OUT.texcoord = IN.texcoord; float3x3 TBN; // tangent space распологаем в мировом пространстве TBN[0] = mul(IN.T, WorldView ); TBN[1] = mul(IN.B, WorldView ); TBN[2] = mul( IN.N, WorldView ); // А light в пространстве tangent space float3 light = mul(TBN, vLight.xyz); OUT.light = float4(light, 1.0); return OUT; }
sampler TextureBase; sampler NormalMap; float4 main_ps_hlsl( VS_OUT IN ) : COLOR { float4 ColorOut; float4 ColorBase = tex2D( TextureBase, IN.texcoord ); float4 ColorNormal = 2 * (tex2D(NormalMap, IN.texcoord.xy) - 0.5); //convert from [-1;1] to [0;1] float4 light = 0.5 * IN.light + 0.5; float NormalDotLight = dot(ColorNormal.xyz, light.xyz); ColorOut = ColorBase * NormalDotLight; return ColorOut; }
Источники:
http://www.gamedev.net/columns/hardcore/cgbumpmapping/GameDev_net -- Cg Bumpmapping.htm
http://www.blacksmith-studios.dk/projects/downloads/tangent_matrix_derivation.php
HLSL Specular Bump Mapping на gamedev.ru
Просто Bump Mapping на gamedev.ru