轉載請註明處: http://blog.csdn.net/tianhai110
根據深度圖重建物體位置
第一種方法: 儲存 投影后z/w,並結合x/w,y/w, 通過 乘以投影矩陣的逆矩陣 再除以w得到物體的位置;
// 深度pass的頂點shader代碼:<br />output.vPositionCS = mul(input.vPositionOS, g_matWorldViewProj);<br />output.vDepthCS.xy = output.vPositionCS.zw; </p><p>// 深度pass的像素 shader 代碼 (輸出 z/w):<br />return input.vDepthCS.x / input.vDepthCS.y;<br />
另一個延時渲染shader
// 功能:把深度值轉換成視圖空間的頂點位置<br />// vTexCoord 是一個全屏四邊形的紋理座標,x=0是螢幕的左邊, y=0是螢幕的上邊;<br />float3 VSPositionFromDepth(float2 vTexCoord)<br />{<br /> // 擷取這個像素的深度值<br /> float z = tex2D(DepthSampler, vTexCoord);</p><p> // 根據視口的位置擷取x/w和y/w<br /> float x = vTexCoord.x * 2 - 1;<br /> float y = (1 - vTexCoord.y) * 2 - 1;</p><p> float4 vProjectedPos = float4(x, y, z, 1.0f);</p><p> // 乘以投影矩陣的逆矩陣<br /> float4 vPositionVS = mul(vProjectedPos, g_matInvProjection); </p><p> // 除以w來擷取頂點的位置<br /> return vPositionVS.xyz / vPositionVS.w;<br />}</p><p>
第二種方法:儲存歸一化的視圖空間的z來作為我們的深度。 由於視圖空間的深度是線性,這就意味著我們能夠獲得均勻的分布,而不必投影和逆投影,來還原頂點的位置。 我們只需要通過該深度值,乘以一條指向視錐體遠截面的射線,就能夠重建頂點的位置。
渲染線性深度
void DepthVS( in float4 in_vPositionOS : POSITION,<br /> out float4 out_vPositionCS : POSITION,<br /> out float out_fDepthVS : TEXCOORD0 )<br />{<br /> // 計算出頂點在view空間和clip空間的位置<br /> float4x4 matWorldView = mul(g_matWorld, g_matView);<br /> float4 vPositionVS = mul(in_vPositionOS, matWorldView);<br /> out_vPositionCS = mul(vPositionVS, g_matProj);<br /> out_fDepthVS = vPositionVS.z;<br />}</p><p>float4 DepthPS(in float in_fDepthVS : TEXCOORD0) : COLOR0<br />{<br /> // z值 取反併除以遠截面的距離(以便深度值位於[0,1]之間)<br /> //(如果是左手座標系 不要負號)<br /> float fDepth = -in_fDepthVS/g_fFarClip;<br /> return float4(fDepth, 1.0f, 1.0f, 1.0f);<br />}</p><p>
延時shader來重建頂點位置
//渲染一個全屏的四邊形,頂點shader如下:<br />void QuadVS ( in float3 in_vPositionOS : POSITION,<br /> in float3 in_vTexCoordAndCornerIndex : TEXCOORD0,<br /> out float4 out_vPositionCS : POSITION,<br /> out float2 out_vTexCoord : TEXCOORD0,<br /> out float3 out_vFrustumCornerVS : TEXCOORD1 )<br />{<br /> // 位移半個像素的位置<br /> out_vPositionCS.x = in_vPositionOS.x - (1.0f/g_vOcclusionTextureSize.x);<br /> out_vPositionCS.y = in_vPositionOS.y + (1.0f/g_vOcclusionTextureSize.y);<br /> out_vPositionCS.z = in_vPositionOS.z;<br /> out_vPositionCS.w = 1.0f;</p><p> // 傳遞紋理座標 和 視錐體頂叫位置。 這些頂點位置是經過插值的,以便像素shader能夠通過射線來查詢頂點的位置<br /> out_vTexCoord = in_vTexCoordAndCornerIndex.xy;<br /> out_vFrustumCornerVS = g_vFrustumCornersVS[in_vTexCoordAndCornerIndex.z];<br />}</p><p>// 像素shader:用於重建viewSpace下的位置<br />float3 VSPositionFromDepth(float2 vTexCoord, float3 vFrustumRayVS)<br />{<br /> float fPixelDepth = tex2D(DepthSampler, vTexCoord).r;<br /> return fPixelDepth * vFrustumRayVS;<br />}</p><p>
g_vFrustumCornersVS 為視錐體遠截面上的四個頂點。