第一种方法: 存储 投影后z/w,并结合x/w,y/w, 通过 乘以投影矩阵的逆矩阵 再除以w得到物体的位置;
[c-sharp]
view plain
copy
- // 深度pass的顶点shader代码:
- output.vPositionCS = mul(input.vPositionOS, g_matWorldViewProj);
- output.vDepthCS.xy = output.vPositionCS.zw;
- // 深度pass的像素 shader 代码 (输出 z/w):
- return input.vDepthCS.x / input.vDepthCS.y;
另一个延时渲染shader
[c-sharp]
view plain
copy
- // 功能:把深度值转换成视图空间的顶点位置
- // vTexCoord 是一个全屏四边形的纹理坐标,x=0是屏幕的左边, y=0是屏幕的上边;
- float3 VSPositionFromDepth(float2 vTexCoord)
- {
- // 获取这个像素的深度值
- float z = tex2D(DepthSampler, vTexCoord);
- // 根据视口的位置获取x/w和y/w
- float x = vTexCoord.x * 2 - 1;
- float y = (1 - vTexCoord.y) * 2 - 1;
- float4 vProjectedPos = float4(x, y, z, 1.0f);
- // 乘以投影矩阵的逆矩阵
- float4 vPositionVS = mul(vProjectedPos, g_matInvProjection);
- // 除以w来获取顶点的位置
- return vPositionVS.xyz / vPositionVS.w;
- }
第二种方法:存储归一化的视图空间的z来作为我们的深度。 由于视图空间的深度是线性的,这就意味着我们能够获得均匀的分布,而不必投影和逆投影,来还原顶点的位置。 我们只需要通过该深度值,乘以一条指向视锥体远截面的射线,就能够重建顶点的位置。
渲染线性深度
[c-sharp]
view plain
copy
- void DepthVS( in float4 in_vPositionOS : POSITION,
- out float4 out_vPositionCS : POSITION,
- out float out_fDepthVS : TEXCOORD0 )
- {
- // 计算出顶点在view空间和clip空间的位置
- float4x4 matWorldView = mul(g_matWorld, g_matView);
- float4 vPositionVS = mul(in_vPositionOS, matWorldView);
- out_vPositionCS = mul(vPositionVS, g_matProj);
- out_fDepthVS = vPositionVS.z;
- }
- float4 DepthPS(in float in_fDepthVS : TEXCOORD0) : COLOR0
- {
- // z值 取反并除以远截面的距离(以便深度值位于[0,1]之间)
- //(如果是左手坐标系 不要负号)
- float fDepth = -in_fDepthVS/g_fFarClip;
- return float4(fDepth, 1.0f, 1.0f, 1.0f);
- }
延时shader来重建顶点位置
[c-sharp]
view plain
copy
- //渲染一个全屏的四边形,顶点shader如下:
- void QuadVS ( in float3 in_vPositionOS : POSITION,
- in float3 in_vTexCoordAndCornerIndex : TEXCOORD0,
- out float4 out_vPositionCS : POSITION,
- out float2 out_vTexCoord : TEXCOORD0,
- out float3 out_vFrustumCornerVS : TEXCOORD1 )
- {
- // 偏移半个像素的位置
- out_vPositionCS.x = in_vPositionOS.x - (1.0f/g_vOcclusionTextureSize.x);
- out_vPositionCS.y = in_vPositionOS.y + (1.0f/g_vOcclusionTextureSize.y);
- out_vPositionCS.z = in_vPositionOS.z;
- out_vPositionCS.w = 1.0f;
- // 传递纹理坐标 和 视锥体顶叫位置。 这些顶点位置是经过插值的,以便像素shader能够通过射线来查询顶点的位置
- out_vTexCoord = in_vTexCoordAndCornerIndex.xy;
- out_vFrustumCornerVS = g_vFrustumCornersVS[in_vTexCoordAndCornerIndex.z];
- }
- // 像素shader:用于重建viewSpace下的位置
- float3 VSPositionFromDepth(float2 vTexCoord, float3 vFrustumRayVS)
- {
- float fPixelDepth = tex2D(DepthSampler, vTexCoord).r;
- return fPixelDepth * vFrustumRayVS;
- }
g_vFrustumCornersVS 为视锥体远截面上的四个顶点。