如何由Height Map生成Normal Map

Nvidia和ATI都有相应的工具把Heightmap转成NormalMap,有了NormalMap,我们就可以用NormalMapping技术进行Per Pixel Lighting计算了。那么HeightMap是怎么转化成NormalMap的呢?       其实并不难, 在《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); }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值