learnOpenGL 5.4 视差贴图

高度贴图

视差贴图要用到一副利用R通道储存片元高度的高度贴图,模拟在看到凹凸面的视差。
在这里插入图片描述
如图所示,如果这是一个3D的模型,我们沿黄线方向看到的应当是B点,如果是平面则会看到A点。按着这个逻辑,我们只要在贴图的A点显示B的内容,就可以假乱真,用平面贴图达到3D的效果。

所以,我们要做的工作,就是计算出B点,用它替换A点。

顺便一提,视差贴图一般与法线贴图一同使用,相辅相成。


视差计算

深度比高度更容易模拟,所以我们通常使用深度贴图取反来代替高度图。
在这里插入图片描述
寻找B点的过程如图所示,从T0点出发,将深度分成N份逐层向下遍历,直到找到一点的深度小于等于该层(如图上的T3),则要找的点就在T2,T3之间,在利用相似三角形近似计算出该点的坐标。

以下是利用这个原理写的函数:

vec2 paracoor(vec2 texcoor,vec3 viewdir)
{
	vec2 p=viewdir.xy/viewdir.z*material.heightscale;//视线向量
	float layers=mix(20.0,10.0,abs(dot(vec3(0,0,1.0),viewdir)));//层数
	vec2 deltacoor=p/layers;
	float depth=0.0;
	vec2 currentcoor=texcoor;
	float currentdepth=1.0-texture(material.parawall,currentcoor).r;
	float predepth;
	while(depth<currentdepth)
	{
		depth+=1.0/layers;
		currentcoor-=deltacoor;
		predepth=currentdepth;
		currentdepth=1.0-texture(material.parawall,currentcoor).r;
	}
	float ratio=(depth-currentdepth)/(depth-currentdepth+predepth-(depth-1.0/layers));
	return (currentcoor+ratio*deltacoor);
}

p是视线的向量,viewdir.xy / viewdir.z 是为了使z分量=1,实际上是viewdir.xyz / viewdir.z,但是P是二维向量,所以只取xy。heightscale是一个系数,用来调整视差的强烈程度。

为了提高算法效率,当视线方向比较正的时候取样层数可以少一些,比较斜的时候应该多一些,所以用了一个mix函数来改变层数。

其他部分与法线贴图基本相同。

局限

一个3D模型的表面积显然是要大于一个平面的,所以3D上的信息一定大于平面。视差贴图实际上是反复使用临近的信息来补足丢失的信息,所以只有当模拟的3D物体颜色信息本身就重复性比较大时才显得比较真实。所以一般还是用来模拟墙壁等细节要求较低的地方。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值