现在的位置: 首页 > 综合 > 正文

DirectX Sample-ParallaxOcclusionMapping视差贴图技术

2018年05月03日 ⁄ 综合 ⁄ 共 2275字 ⁄ 字号 评论关闭

这个例子主要说明ParallaxOcclusionMapping,同时采用了另外两种方法作为对比:Bump mapping和Parallax mapping with offset limiting。

从简单到复杂为BUMPMAP、PM、POM,本文按此顺序说明。

Bump mapping

这种方法就是简单的法向贴图。

VS输入为pos、tex、normal

需要计算出输入到PS的vLightTS和vViewTS,其中vViewTS计算镜面反射光使用。

世界空间:

vLightWS=g_LightDir

vViewWS=g_vEye-vPositionWS

转换到切线空间:

vLightTS = mul( vLightWS, mWorldToTangent );

vViewTS  = mul( mWorldToTangent, vViewWS  );

PS输入为tex、vLightTS、vViewTS

计算结果通过公用函数ComputeIllumination:

// 采样法向贴图得到像素法向

float3 vNormalTS = normalize( tex2D( tNormalHeightMap, texCoord ) * 2 - 1 );

// 采样纹理贴图

float4 cBaseColor = tex2D( tBase, texCoord );

// Compute diffuse color component:
float3 vLightTSAdj = float3( vLightTS.x, -vLightTS.y, vLightTS.z );   
float4 cDiffuse = saturate( dot( vNormalTS, vLightTSAdj )) * g_materialDiffuseColor;
   
// Compute the specular component if desired:  
float4 cSpecular = 0;
if ( g_bAddSpecular )
{
    float3 vReflectionTS = normalize( 2 * dot( vViewTS, vNormalTS ) * vNormalTS - vViewTS );
           
     float fRdotL = saturate( dot( vReflectionTS, vLightTSAdj ));
     cSpecular = saturate( pow( fRdotL, g_fSpecularExponent )) * g_materialSpecularColor;
}
   
// Composite the final color:
float4 cFinalColor = (( g_materialAmbientColor + cDiffuse ) * cBaseColor + cSpecular ) * fOcclusionShadow; 
   
return cFinalColor;  

Parallax mapping with offset limiting

这种方法可以参考文章。这篇原始论文里面描述了这个带限制的视差偏移技术的原理。改算法原理是计算纹理坐标的时候考虑到渲染像素的高度,计算合适的纹理坐标,而不是直接采用vertexshader提供的纹理坐标。

这种方法的计算方法与上面的bumpmap基本相同,仅有一点区别:在调用ComputeIllumination计算像素值之前,根据物体存储在法向贴图中的高度信息(alpha分量),对纹理坐标进行偏移。

具体计算过程如下(只列出与bumpmap不同部分)

// alpha通道保存的是高度信息
float fCurrentHeight = tex2D( tNormalHeightMap, i.texCoord ).a;
   
// 根据程序设置计算当前高度的实际偏移值:
float fHeight = fCurrentHeight * g_fHeightMapScale + sfHeightBias;
   
// 如果需要限制偏移值,把这行注掉
fHeight /= vViewTS.z;
   
// 根据视觉方向在切线空间中的坐标值进行偏移,制造视差效果:
float2 texSample = i.texCoord + vViewTS.xy * fHeight;

最后给出一个例子运行中的一个可能数据:

假设物体是一个法向正对摄像机的平面,可以分3种情况说明:

1.对于摄像机正对的平面上的点,此时vViewTS=(0,0,1)

2.对于摄像机正对点左边的点,此时vViewTS的一个可能值为(0.1,0,0.9),根据下面算法,这个点计算纹理坐标的时候取一个稍微偏右的坐标值

3.对于摄像机正对点右边的点,此时vViewTS的一个可能值为(-0.1,0,0.9),根据下面算法,这个点计算纹理坐标的时候取一个稍微偏左的坐标值

另一个调试例子:

g_LightDir:{-0.5, 0, -0.866}

物体沿y轴转90°,这样正面对着摄像机,对可见点调试如下:

vNormal{0, 0, -1}

vTangent{1, 0, 0}

vBinormal{0, 1, 0}

vLightTS{-0.5, 0, 0.866}

ParallaxOcclusionMapping

上面的方法PM计算一个大致的便宜,不是很准确,POM则计算精确的偏移纹理坐标,同时还可以生成阴影,缺点是算法复杂度大,PS中需要采样周围纹理进行计算,相应的论文:

PPT:Practical Parallax Occlusion Mapping for Highly Detailed Surface Rendering

论文:Dynamic Parallax Occlusion Mapping with Approximate Soft Shadows

转载一篇博客。里面讲的挺好

抱歉!评论已关闭.