當前位置:編程學習大全網 - 編程語言 - 如何從height map生成normal map

如何從height map生成normal map

其實並不難,在《3D遊戲與計算機圖形學方法》中,提供了壹種由高度圖生成法向圖的方法。其思想是根據高度圖中的象素與其周圍象素的高度差,在切空間構造S向量和T向量,由SXT得到法線向量。

設H(i,j)表示在height map上(i,j)象素點的高度值,則在切線空間S和T方向的切向量可以表示成:

S(i,j) = (1,0,H(i+1,j) - H(i-1,j) )

T(i,j) = (0,1,H(i,j+1) - H(i,j-1) )

Normal(i,j) = S(i,j) X T(i,j)

H(i+1,j) – H(i-1,j)為沿S方向的高度差,也就是S方向的坡度,H(i,j+1) - H(i,j-1)為沿T方向的高度差,也就是T方向的坡度。當相鄰象素高度差為0時,則算出的Normal(i,j) = (0,0,1),表示法線垂直於平面,當有高度差時,法線就會分別朝S方向或T方向偏移。

用shader來實現也很簡單,VS和PS代碼如下,上邊左圖為HeightMap,右圖為由下面shader生成的NormalMap,這個方法生成的NormalMap並不夠好,在RenderMonkey中有壹個叫NormalmapFilter的Sample,會生成更高質理的NormalMap,有興趣的朋友可以參考。

VS_OUTPUT main(float4 Pos: POSITION){

VS_OUTPUT Out;

// Clean up inaccuracies

Pos.xy = sign(Pos.xy);

Out.Pos = float4(Pos.xy, 0, 1);

// Image-space

Out.texCoord.x = 0.5 * (1 + Pos.x);

Out.texCoord.y = 0.5 * (1 - Pos.y);

return Out;

}

float4 main(float2 texCoord: TEXCOORD) : COLOR {

float2 off = 1.0 / HeightMapSize;

float Scale = 1;

// Sample teh neighbor

float s0 = tex2D(Heightmap, texCoord + float2(-off.x,0)).r;

float s1 = tex2D(Heightmap, texCoord + float2( off.x,0)).r;

float s2 = tex2D(Heightmap, texCoord + float2( 0,-off.y)).r;

float s3 = tex2D(Heightmap, texCoord + float2(0,off.y)).r;

float3 U = float3(1,0,s1 - s0);

float3 V = float3(0,1,s3 - s2);

float3 normal = normalize(Scale * cross(U,V));

// Pack [-1, 1] into [0, 1]

return float4(normal * 0.5 + 0.5,1);

}

  • 上一篇:那淮北壹中和宿城壹中那個好?
  • 下一篇:it培訓機構靠譜嗎
  • copyright 2024編程學習大全網