視差貼圖(Parallax Mapping)
原理:
PixelShader
//PixelShader
float4 RenderScenePS( VS_OUTPUT In ) :COLOR0
{
// 計算視差貼圖的偏移
float3 ViewDir = normalize( In.vLookAt );
float2 OffsetUV = In.TextureUV ;
float3 h = tex2D( MeshHeightSampler ,In.TextureUV ).y ;
OffsetUV += float2( -ViewDir.x , ViewDir.y ) * ( h * 0.04 - 0.02 );
float4 texColor = tex2D( MeshTextureSampler ,OffsetUV );
//
return texColor ;
}
VS_OUTPUT RenderSceneVS( VS_INPUT In )
{
VS_OUTPUT Out = ( VS_OUTPUT )0;
//正常流程變化模型的頂點
float4x4 matWorldView = mul( g_matWorld ,g_matView );
float4x4 matWorldViewProject = mul( matWorldView ,g_matProject );
Out.Position = mul( In.Position , matWorldViewProject );
Out.TextureUV = In.TextureUV;
//----------------- 在此計算一個變換矩陣 ---------------------
// 將世界座標變換到切線空間系的變換矩陣
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 );
// 每個頂點上的指向觀察者的方向
Out.vLookAt = mul ( matWorldToModel ,normalize( Position - g_vEyePosition ));
return Out;
}
陡峭視差貼圖Steep Parallax Mapped
原理:
陡峭視差映射的工作方式在下面的圖片上舉例。深度被分割成8個層,每層的高度值是0.125。每層的紋理座標偏移是V.xy/V.z * scale/numLayers。從頂層黃色方塊的位置開始檢查,下面是手動計算步驟:1.層的深度爲0,高度圖深度H(T0)大約爲0.75。採樣到的深度大於層的深度,所以開始下一次迭代。
2.沿着V方向偏移紋理座標,選定下一層。層深度爲0.125,高度圖深度H(T1)大約爲0.625。採樣到的深度大於層的深度,所以開始下一次迭代。
4.沿着V方向偏移紋理座標,選定下一層。層深度爲0.375,高度圖深度H(T3)大約爲0.2。採樣到的深度小於層的深度,所以向量V上的當前點在表面之下。我們找到了紋理座標Tp=T3是實際交點的近似點。
vec2 steepPallaxMapping(in vec3 v, in vec2 t)
{
// determine number of layers from angle between V and N
const float minLayers = 5;
const float maxLayers = 15;
float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0, 0, 1), v)));
// height of each layer
float layerHeight = 1.0 / numLayers;
// depth of current layer
float currentLayerHeight = 0;
// shift of texture coordinates for each iteration
vec2 dtex = gHeightScale * v.xy / v.z / numLayers;
// current texture coordinates
vec2 currentTextureCoords = t;
// get first depth from heightmap
float heightFromTexture = texture(NormTexSampler, currentTextureCoords).a;
// while point is above surface
while(heightFromTexture > currentLayerHeight)
{
// to the next layer
currentLayerHeight += layerHeight;
// shift texture coordinates along vector V
currentTextureCoords -= dtex;
// get new depth from heightmap
heightFromTexture = texture(NormTexSampler, currentTextureCoords).a;
}
return currentTextureCoords;
}
Demo 下載