6.6视差贴图
关于视差贴图,我的理解是微调获得凹凸感。
材料:1,颜色纹理,2,法线纹理,3,高度纹理。
其他需要参数:视点位置
类比下大地基准面,大地基准面模拟地球表面。同样,大地基准面+深度信息纹理 = 地球表面。
就是说,要把白菜吃出鸡腿的味道,那就只能加佐料,这个佐料就是深度信息纹理。当然,白菜不是真正的鸡腿,所以只能偶尔吃吃,就像小时候吃的人造肉,偶尔解解馋还行,真把人造肉当肉吃,那就营养不良了。
这个视点位置作用,就是我要四处看看到底像不像真实物体。东咬一口,嗯,是这个味道,西咬一口,好像还是这个味道,于是,成功被骗了。
好,那么看看这个高度纹理,首先,这肯定是模型坐标系中的数值,记录模型的某个位置与实际位置的高度差。
在vs里,需要将世界坐标变换到模型空间的变换矩阵
float3x3 matWorldToModel = float3x3( mul(In.Tanget, g_matWorld ).xyz, mul( cross(In.Tanget, In.Normal), g_matWorld ).xyz, mul(In.Normal, g_matWorld).xyz );
float4 Position = mul(In.Position, g_matWorld );
然后计算高度差
Output.vLookAt = mul( matWorldToModel, normalize(Position - g_vEyePosition ));
看过了高度,再看纹理,如何对应上。因为与视角相关,所以计算视差贴图时,就要考虑视角因素,也就是vs里计算出来的高度差。(模型坐标系),当然,颜色自然是在Ps中考虑了
//计算视差贴图的偏移
float3 viewDir = normalize(In.vLookAt);
//根据偏移采样高度纹理,得到一个系数因子
float3 h = tex2D(MeshHeightSampler, In.TextureUV ).y;
有个简化公式,
offsetUV = offsetUV + float2(viewDir.x, viewDir.y) * v2Scale;
在Ps中就体现为
offsetUV += float2(-viewDir.x, viewDir.y) * ( h * 0.04 - 0.02 );
这里就体现出了纹理坐标的偏移,从而感到了纹理坐标的凹凸起伏
return tex2D(MeshTextureSampler, offsetUV);
从vs里看,要保证切线空间可用,因此在c++程序里,需要加上判断
//计算切向量
hr = D3DXComputeTangent(m_pMeshSysMemory, 0, 0, 0, TRUE, NULL);
if (FAILED(hr))
{
return hr;
}