找回密码
 立即注册
首页 业界区 科技 《Fundamentals Of Computer Graphics》第二章 杂项数学 ...

《Fundamentals Of Computer Graphics》第二章 杂项数学 总结

筒霓暄 昨天 10:22
开篇

  第二章“Miscellaneous Math”讲了许多高中、大学所学的一些基础数学知识:集合、映射、区间、三角函数、积分、密度函数等等。不过我觉得还是有一些要注意的地方。
立体角与球面三角学(Solid Angles and Spherical Trigonometry)

  传统的三角学涉及的是平面上的三角形,三角形其实也能定义在非平面表面。这种三角学在许多领域例如天文学出现,研究这些三角形的领域叫球面三角学。它虽然不会经常在图形学中被使用,但是出现的时候一般都非常重要。
  在球面三角学中对计算机图形学非常重要的一个概念叫做立体角Solid Angle),立体角让我们可以量化例如在天上的飞机占据视野的多少。整个测量过程其实很简单,把能“看到”飞机的所有方向投影到单位球,接着测量面积。测量出的面积大小就是立体角的大小,不过立体角的单位是SrSteradian),在单位球上的总立体角就是\(4\pi\,\mathrm{sr}\)。
  我还稍微查了下资料,wiki百科上还给出了立体角积分公式,这里可以稍微了解一下,能让你对立体角有更好的理解。首先通过\(\Delta \theta\)和\(\Delta \varphi\)分割半径为\(r\)的球面,如图所示。
1.png

作者:Travailen
当\(\Delta \theta\)和\(\Delta \varphi\)在极小情况下,这个时候分割出来的每一极小份的曲面可以被当作一个矩形。因此这个时候的极小份的面积为

\[dA = (r\,\sin\theta\,d\varphi)(rd\theta) = r^2(\sin\theta\,d\theta\,d\varphi)\]
当\(r=1\)时,极小立体角的大小就是极小面积的大小

\[d\Omega = \sin\theta\,d\theta\,d\varphi\]
因此立体角的积分公式为

\[\Omega = \int \int_{S} \sin\theta\,d\theta\,d\varphi \]
单位正交基的确定

  有时候需要为给定的向量求一个标准正交基,比如在写全屏光线追踪着色器,这个时候要为每个像素发出光线,此时就需要一个标准正交基。对于给定的向量\(\mathbf{a}\),我们需要标准正交基\(\mathbf{u}\)、\(\mathbf{v}\)、\(\mathbf{w}\)。其中\(\mathbf{w}\)与\(\mathbf{a}\)方向一致,\(\mathbf{u}\)、\(\mathbf{v}\)一般不关心是什么。书中还是给了两种方法
从一个辅助向量构造(Constructing a Basis from a Single Vector)

  这个方法实际上就是挑选一个不与\(\mathbf{w}\)共线的一个辅助向量\(\mathbf{t}\),值得注意的是辅助向量\(\mathbf{t}\)不可与\(\mathbf{w}\)过于接近,\(\mathbf{u}\)、\(\mathbf{v}\)、\(\mathbf{w}\)可以如下计算

\[\mathbf{w}=\frac{\mathbf{a}}{||\mathbf{a}||} \]

\[\mathbf{u}=\frac{\mathbf{t} \times \mathbf{w}}{||\mathbf{t} \times \mathbf{w}||}\]

\[\mathbf{v}=\mathbf{w} \times \mathbf{u}\]
从两个辅助向量构造(Constructing a Basis from Two Vectors)

  使用这个方法需要最好挑选两个垂直的向量\(\mathbf{a}\)、\(\mathbf{b}\),要注意的是向量\(\mathbf{a}\)、\(\mathbf{b}\)不可过于接近,这个时候可以求出\(\mathbf{u}\)、\(\mathbf{v}\)、\(\mathbf{w}\)

\[\mathbf{w}=\frac{\mathbf{a}}{||\mathbf{a}||}\]

\[\mathbf{u}=\frac{\mathbf{b} \times \mathbf{w}}{||\mathbf{b} \times \mathbf{w}||}\]

\[\mathbf{v}=\mathbf{w} \times \mathbf{u}\]
由重心坐标得到三角形上的点的证明

  对于在三角形上的给定一点\(\mathrm{P}\),可以得到\(\vec{P} = \alpha \vec{A}+\beta\vec{B}+\gamma\vec{C}\),其中\(\alpha+\beta+\gamma=1\)。书上的证明实在是太复杂了,我想了想其实有更好的几何证明方法。
在三角形\(\mathrm{ABC}\)上做\(\mathrm{DE}\)平行于\(\mathrm{AC}\),接着在线段\(\mathrm{DE}\)上取一点\(\mathrm{P}\),如下图所示。
2.png

如图所示,现在可由两个系数\(k\)与\(t\)确定三角形\(\mathrm{ABC}\)上一点

\[\vec{P} = \vec{B}+(1-t)(1-k)(\vec{A}-\vec{B})+t(1-k)(\vec{C}-\vec{B})\]
化简可得

\[\vec{P}=(1-t-k+tk)\vec{A}+k\vec{B}+(t-tk)\vec{C}=\alpha\vec{A}+\beta\vec{B}+\gamma\vec{C}\]
易得

\[\alpha=1-t-k+tk\]

\[\beta=k\]

\[\gamma=t-tk\]
因此可证得\(\alpha+\beta+\gamma=1\)
蒙特卡洛积分(Monte Carlo Integration)

  蒙特卡洛积分实际上就是通过随机样本来对函数的某区域进行积分
现要求沿表面法线方向的半球的入射光线所贡献的辐照度

\[H(\mathbf{n})=\int_{\Omega} L_f(\omega_i) \, (\mathbf{n} \cdot \omega_i) \, d\omega_i\]
可以通过数量为\(\mathrm{N}\)的随机采样点来获得辐亮度的积分值,因此每个采样点的权重是\(\frac{2\pi}{\mathrm{N}}\),由此可写如下代码
  1. const float3 dir = octDecode(coor.x, coor.y);
  2. float3 result = float3(0.0, 0.0, 0.0);
  3. [unroll]
  4. for (uint i = 0; i < SAMPLECOUNT; i++)
  5. {
  6.     const float3 randDir = randomDirection[i] * sign(dot(dir, randomDirection[i]));
  7.     const float3 radiance = envCube.SampleLevel(linearClampSampler, randDir, 0.0).rgb;
  8.     result += radiance * saturate(dot(dir, randDir));
  9. }
  10.         
  11. result = 2.0 * PI / float(SAMPLECOUNT) * result;
复制代码
重要性采样(Importance Sampling)

  当被积函数在积分区域内的值有很大的变化时,我们可以把采样点集中分布在一些区域,不过这个时候每个采样点都有特定的非均匀权重。如果我们知道概率密度函数\(\mathrm{PDF}\)就能求出积分值,代码如下
  1. const float3 dir = octDecode(coor.x, coor.y);
  2. float3 result = float3(0.0, 0.0, 0.0);
  3. [unroll]
  4. for (uint i = 0; i < SAMPLECOUNT; i++)
  5. {
  6.     const float3 randDir = randomDirection[i] * sign(dot(dir, randomDirection[i]));
  7.     const float3 radiance = envCube.SampleLevel(linearClampSampler, randDir, 0.0).rgb;
  8.     result += radiance * saturate(dot(dir, randDir)) / directionImportance[i];
  9. }
  10.         
  11. result = 1.0 / float(SAMPLECOUNT) * result;
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册