层次化Z缓冲区拣选算法学习笔记
1 Nick Darnell的Hiz算法总结和分析笔记 基于层次化Z缓冲区的遮挡拣选(Hierarchical Z-buffer occlusion culling)的实现方式有多种,其中有一种是基于论文Real-Time Rendering (Section 3.3.3)。
1.1 层次化Z缓冲区(Hierarchical Z-buffer,HiZ)剔除步骤 让美术准备好用来遮挡住其他物体的遮挡体(occlusion geometry) CPU端:获取到所有的遮挡体,且将在视截体之外的给剔除掉 GPU端:把上一步剔除剩下的遮挡体,将其深度值渲染到深度缓冲区D-RT0 GPU端:对D-RT0进行采样,并填充整个mipchain CPU端:对当前场景中的所有可见物体,获取到其物体的包围球 GPU端:把上一步获取到的物体包围球,计算该包围球对应的屏幕空间宽度,然后使用该宽度计算 mip 级别,从步骤 4 中生成HiZ 贴图中进行采样 CPU端:读回计算着色器的缓冲区输出 1.2 对分层Z缓冲区进行降采样的HLSL代码 上述步骤中的第4步用到的降采样的方式如下:
取当前的,右边一个、下方一个和右下方一个像素进行比较,取其值最大者,作为降采样像素中的新深度值。下面两个图是降采样前后版本的示例,黑色表示较近的深度,像素越白,深度值越远/越高。
降采样HLSL代码如下所示
float4 vTexels; vTexels.x = LastMip.Load( nCoords ); vTexels.y = LastMip.Load( nCoords, uint2(1,0) ); vTexels.z = LastMip.Load( nCoords, uint2(0,1) ); vTexels.w = LastMip.Load( nCoords, uint2(1,1) ); float fMaxDepth = max( max( vTexels.x, vTexels.y ), max( vTexels.z, vTexels.w ) ); 1.3 层次化Z缓冲区的剔除核心算法 cbuffer CB { matrix View; matrix Projection; matrix ViewProjection; float4 FrustumPlanes[6]; // 视截体的6个面,基于世界坐标,每个面的法线朝外 float2 ViewportSize; // 视口的高和宽,基于像素 float2 PADDING; }; // GPU只读的缓冲区,因为声明了使用t0着色器,故而每一个点是一个float4 // float4的xyz分量记录了包围球的球心坐标,w分量记录了球的半径。基于 // 世界坐标系 StructuredBuffer Buffer0 : register(t0); // Is Visible 1 (Visible) 0 (Culled) // GPU可读写的缓冲区,每一个点是一个uint,值为1时该点可视,0时该点不可视 RWStructuredBuffer BufferOut : register(u0); Texture2D HizMap : register(t1); SamplerState HizMapSampler : register(s0); // 计算给定的点vPoint到平面方程的距离 // vPlane: 四个xyzw分量,分别包含了平面方程的四个系数abcd: ax + by + cz = d // vPoint: Point to be tested against the plane.