从Height Map得到Normal Map的方法

gongminmin
一般来说,Normal Map来自于Height Map。具体生成的方法如下:
把Height Map的每个像素和它上面的一个像素相减,得到一个高度差,作为该点法线的x值;
把Height Map的每个像素和它右边的一个像素相减,得到一个高度差,作为该点法线的y值;
取1作为该点法线的z值。

推导过程如下:
x方向,每个像素和它下面的一个像素相减,得到向量<1, 0, hb - ha>,其中ha是该像素的高度值,hb是下一行的高度值;
y方向,每个像素和它左边的一个像素相减,得到向量<0, 1, hc - ha>,其中ha是该像素的高度值,hb是左一列的高度值;
两个向量Cross,得到

简单来说,就是取两个方向的切线向量,对它们做Cross得到该点的法线向量。

--------------------------------------------------------------------------------

gongminmin
当然,最后要进行一个normalize

--------------------------------------------------------------------------------

Pointer
还有另外一种做法,是根据每个象素四边的点计算,而该点象素本身不参与计算。
没有试过,不知道哪种好一些。

而且我觉得这种计算只适合于单块的HeightMap、NormalMap,像是DOOM3中的NormalMap就无法由HeightMap计算出来了。所以最好还是在美工建模的时候同时生成NormalMap和HeightMap而不是利用HeightMap生成NormalMap。

--------------------------------------------------------------------------------

AntSam
一般来说,Normal Map来自于Height Map。具体生成的方法如下:
把Height Map的每个像素和它上面的一个像素相减,得到一个高度差,作为该点法线的x值;
把Height Map的每个像素和它右边的一个像素相减,得到一个高度差,作为该点法线的y值;
取1作为该点法线的z值。

推导过程如下:
x方向,每个像素和它下面的一个像素相减,得到向量<1, 0, hb - ha>,其中ha是该像素的高度值,hb是下一行的高度值;
y方向,每个像素和它左边的一个像素相减,得到向量<0, 1, hc - ha>,其中ha是该像素的高度值,hb是左一列的高度值;
两个向量Cross,得到

简单来说,就是取两个方向的切线向量,对它们做Cross得到该点的法线向量。

在nvidia的sample里看到过这个代码,有点疑问:ha, hb, hc是否是归一化到【0,1】之间。。。

--------------------------------------------------------------------------------

gongminmin
在计算的时候ha, hb, hc不归一化,用整数来算
计算结果/255.0f,然后对结果向量归一化

--------------------------------------------------------------------------------

zbo
注意你很久了~你钻研了那么多,有没有做一个好的demo给大家展示一下你的研究成果

--------------------------------------------------------------------------------

gongminmin
我的demo都是一个demo演示一项技术
没有做集成

--------------------------------------------------------------------------------

Pointer
说错了。 :p

多谢华山提醒,DOOM3里面的HeightMap也是用于计算NormalMap的。
不过不同的是_local纹理里面是用于PolyBump的NormalMap,而由HeightMap生成的NormalMap则是用于DetailBump的。

不过由HeightMap生成NormalMap的方式却不尽相同。加上gongminmin兄介绍我,我一共找到三种:

假设当前象素为c,与c相邻的有a b d e。如下所示:

*a*
bcd
*e*

1 The Cg Tutorial中介绍的
s = <1, 0, ha - hc>
t = <0, 1, hd - hc>

2 Mathematics for 3D Game Programming & Computer Graphics中介绍的
s = <1, 0, hd - hb>
t = <0, 1, he - ha>
btw:nVIDIA自己的BumpMapping例子倒和这个一样。

3 gongminmin兄介绍的
s = <1, 0, he - hc>
t = <0, 1, hb - hc>

由三种方式得到的NormalMap也完全不同。

我改了一下nVIDIA的ParallaxMapping例子,大家可以看一下效果。

我觉得Mathematics for 3D Game Programming & Computer Graphics中的做法要好一些。
事实上NV这个Demo里用的也是这种方法。

--------------------------------------------------------------------------------

charls
个人认为你所说的第二种方法比较好。第1&3基本一样,也就是取face的tangent然后cross,所做出的normal不是很光滑,你说3种方法得到的normal都不一样是当然的了,第二种得到的是smooth normal, 第1&3的是其点不同邻face的normal。(不过对于normal map来说是看不是很出来啦)
第二种方法,也就是用其周围四点进行计算。
如此就可以生成比较smooth的normal,因为我们对于一般的model的normal进行smooth都是取某一顶点然后取其相临的faces的average,而对于height map,我们一样取其相邻4个faces然后average。(不过由于其相邻faces都是已知,所以大大化解计算)
你可以用叉乘的公式自己推导一下,最终自己那个点(也就是c)会被约掉啦! :D

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值