1、Per-Vertex SH Data Generation with D3DX
D3DX函数产生的数据是SH系数的集合,可以跨平台使用。
对于Per-Vertex SH coefficient,使用D3DXSHPRTSimulation
1
2
3
4
5
|
HRESULT
WINAPI D3DXSHPRTSimulation(
UINT
Order,
LPD3DXMESH *ppMeshArray,D3DXSHMATERIAL **ppMaterials,
UINT
NumRays,
UINT
NumBounces,
BOOL
EnableSubSurfaceScattering,
FLOAT
LengthScale,
BOOL
EnableSpectral,LPD3DBUFFER *ppResultBuffer,
LPD3DXSHPRTSIMCB pProgressCallback);
|
上面的函数为preconputed radiance transfer(PRT)生成SH系数。该函数是一个离线函数,不能在实时调用。
现在得到了SH系数的集合,但是系数的个数可能很多,比如一个order=5(即带宽l=5)的模拟,每个顶点需要5^2=25个颜色值,即75个系数。
DX使用的压缩方法称为Clustered Principal Component Analysis(CPCA)。
如上图,每一个箭头代表一组SH系数。实际上,一组SH系数可以看成一个多维数组。
如果观察模型中多个顶点的SH系数,可以讲多组SH系数组成集群。例如,平面中相邻的顶点会有相似的系数组。
上图是将不同的SH系数组划分到集群。
我们要首先找出每一个集群中SH系数组的平均值,如下图:
接下来,找出n组SH系数来代表这个集群(必须是最能代表这个集群的SH系数组),被找出来的n个SH系数组被称为PCA。下图展示了n=2的情况:
最后,每一个顶点的SH系数组都可以由这n个系数组线性插值得到,如下图:
上上一篇我们说到,计算每个顶点的最终颜色值可以通过转移方程的SH系数和光线的SH系数求点积得到,这里,因为我们用另一种方式表示转移方程的SH系数,所以最终颜色值的计算方法也可以换一种方式,公式如下:
M代表集群的平均值,B代表若干个挑选出来的值,w代表每一个值的权重。
这样,这种方法让你可以用n个权重值来表示没一个顶点的SH系数组,每个顶点只需要存储集群的索引和一系列的权重值。
1
2
3
4
5
|
HRESULT
WINAPI D3DXSHPRTCompress(
UINT
Order,
LPD3DXBUFFER pSHCoefficients,
D3DXCOMPRESSQUALITYTYPE Quality,
UINT
NumClusters,
UINT
NumPCAVectors,
LPD3DXBUFFER *ppResults);
|
最终的buffer存储了每一个集群的n个SH系数组,同时还包含每一个顶点的权重值。
2、Rendering the Per-Vertex SH Solution
现在我们还需要将光线投影到SH基上,得到光照的SH系数。D3DX提供了一系列的函数帮助处理平行光、球形光、锥形光、半球形光。
1
2
|
void
D3DXSHEvalConeLight();
void
D3DXSHEvalDirectionalLight();
|
最后,进行点乘步骤。
3、SH with Cube Maps
除了一系列的基本光源类型,D3DX还提供了从立方贴图中生成SH光照的API。立方贴图支持反射和折射效果,但是这些效果高光度太大而且diffuse不平滑。现在可以通过将立方贴图投影到SH基上来生成平滑的diffuse环境效果。
1
|
void
D3DXSHProjectCubeMap();
|
4、Simple Specular Highlights
SH lighting能很好的支持diffuse light,然而,怎么往既有效果中加入specular元素?
低带宽的SH方案适合diffuse lighting,因为它将光线的低频部分编码进去,而高光需要物体反射光线的高频部分给摄像机。