實時渲染基礎(5)幾何(Geometry)


幾何表示(Geometry Representation)


隱式表面(Implicit Surface)

一個函數定義一個隱式幾何 \(f(x,y,z)=0\)​​。​

  • 容易判斷一個點是在幾何體內部(\(f<0\))還是外部(\(f>0\)​)。

顯式表面(Explicit Surface)

低維參數映射成隱式函數的高維參數。

  • 相對容易采樣,因為低維參數所需參數數量相對少了。
  • 不容易判斷點在幾何體內部/外部(需要將多維參數解算成低維參數,這一步相當麻煩)。

Constructive Soild Geometry

通過幾何體布爾運算合成的幾何體。

有向距離場(Signed Distance Field,SDF)

有向距離場(Signed Distance Field,SDF):輸入一個點,輸出與這個點最近的幾何體距離(有向距離)。

  • SDF 的插值會有着幾何融合的效果(與一般的插值效果很不一樣):

水平集(Level Set Methods):水平集則是一種用來表示 SDF 的存儲結構,因為復雜的幾何組合的 SDF 基本上很難用一個數學函數表示出來。網格存儲近似函數值,坐標通過網格之間的插值可以得到函數輸出。

點雲(Point Cloud)

點的集合,一般涉及三維重建領域。

Polygon Mesh

渲染中最常見的幾何表示法,通過存儲一堆 polygons (往往是三角面 triangles,triangle 一般又有頂點和頂點索引組成)來表示一個 Polygon Mesh。

射線相交(Ray Intersection)


射線的數學形式:\(\mathbf{r}(t)=\mathbf{o}+t \mathbf{d} \quad 0 \leq t<\infty\)

判斷射線與幾何函數 \(f(\mathbf{x})\) 的一般方法就是將射線方程代換掉 \(\mathbf{x}\)

\(f(\mathbf{o}+t \mathbf{d})=0\)

然后解算出 \(t\)​​ 即為相交點,無解時則沒有相交

最后還需要測試是否滿足\(\quad 0 \leq t<\infty\) ,即不為負數。

射線與球面相交

球方程: \((\mathbf{x}-\mathbf{c})^{2}-R^{2}=0\)

\((\mathbf{o}+t \mathbf{d}-\mathbf{c})^{2}-R^{2}= A t^{2}+B t+C=0\)

其中,
\(A=\mathbf{d} \cdot \mathbf{d}\)
\(B=2(\mathbf{o}-\mathbf{c}) \cdot \mathbf{d}\)
\(C=(\mathbf{o}-\mathbf{c}) \cdot(\mathbf{o}-\mathbf{c})-R^{2}\)

解得:

  • \(B^2-4AC<0\)​​​​​ 時,無交點

  • \(B^2-4AC=0\) 時,有1個可能的交點,\(t=\frac{-B}{2 A}\) (若交點不滿足 \(0 \leq t<\infty\),則不相交)

  • \(B^2-4AC>0\) 時,有2個可能的交點,\(t=\frac{-B \pm \sqrt{B^{2}-4 A C}}{2 A}\) (若交點不滿足 \(0 \leq t<\infty\),則該交點不相交)

射線與平面相交

平面方程:\(\left(\mathbf{x}-\mathbf{p}^{\prime}\right) \cdot \mathbf{N}=0\)

\(\left(\mathbf{p}-\mathbf{p}^{\prime}\right) \cdot \mathbf{N}=\left(\mathbf{o}+t \mathbf{d}-\mathbf{p}^{\prime}\right) \cdot \mathbf{N}=0\)

解得:

  • 有1個可能的交點, \(t=\frac{\left(\mathbf{p}^{\prime}-\mathbf{o}\right) \cdot \mathbf{N}}{\mathbf{d} \cdot \mathbf{N}}\) (若交點不滿足 \(0 \leq t<\infty\),則不相交)

射線與三角形相交

  1. 測試射線是否與三角形所在平面相交(若相交,將會得到相交點)
  2. 測試相交點是否在三角形內部

射線與AABB相交

AABB:一個維度由兩個標量表示,例如三維空間下的AABB應有 \((x_0,x_1,y_0,y_1,z_0,z_1)\)​​ 來表示。

輪流與各維度的兩個平面做相交測試,可以預想到每個維度的測試都能獲得兩個解,按一大一小分類成 \(t_{max}\)\(t_{min}\)​​ 。

所有輪(三維是三輪,二維則是兩輪)測試完成之后,有:

\(t_{enter} = max \{t_{min}\}\)

\(t_{exit}=min\{t_{max}\}\)

解得:

  • \(t_{exit} <0\)​​ ,無交點
  • \(t_{exit}>=0\)\(t_{enter} < 0\),意味着射線起點在AABB內部,擁有一個交點 \(t_{exit}\)
  • \(t_{exit} >=0\)​ 且 \(t_{enter}<t_{exit}\)​​ ,兩個交點分別為 \(t_{enter}\)\(t_{exit}\)

網格細分(Mesh Subdivision)


Loop細分算法(Loop Subdivision)

注:Loop是人名,不是循環的意思

Loop細分算法主要是針對基於三角形網格的細分。

進行一輪Loop細分的步驟:

  1. 先將每個三角形拆分成四個小三角形

  1. 每個新頂點(由於三角形拆分而出現的)的位置應為:

\(V_{new} = \frac{3}{8} \cdot (A+B)+\frac{1}{8} \cdot (C+D)\)

其中,\(A\)\(B\) 是新頂點所在邊的兩個端點(即相鄰兩個三角形的共享頂點),而 \(C\)\(D\)​ 則分別是相鄰兩個三角形的非共享頂點。

  1. 最后,每個舊頂點的位置也應該進行調整,應為:

\(V_{old}'=(1-n\cdot u) \cdot V_{old} + u \cdot \sum V_{neighbor}\)

注:舊頂點的位置調整並不依賴於新頂點,而是依賴於它本身和它周圍的舊頂點。

其中, \(n\)​​ ​​​為舊頂點的度(即周圍有多少個舊頂點與它直接相連),而 \(u\)​ 實際上代表着周圍頂點的權重且有如下規則:

\(u=\left\{\begin{array}{l}\frac{3}{16} \ ,n=3\\ \frac{3}{8n} \ ,otherwise \end{array}\right.\)

Loop細分效果圖:

Catmull-Clack 細分算法(Catmull-Clack Subdivision)

Catmull-Clack 細分算法則是支持通用網格(如包含三角形、四邊形)的細分,它的主要想法是每輪細分都在面的中心和邊的中心生成新頂點,然后連接所有這些新頂點即可。

進行一輪 Catmull-Clack (針對四邊形Quad Mesh的情況)細分的步驟:

  1. 先生成每個面的Face point:

\(f=\frac{v_1+v_2+v_3+v_4}{4}\)

  1. 生成每個邊的Edge point:

\(e=\frac{v_1+v_2+f_1+f_2}{4}\)

  1. 調整舊頂點的位置:

\(v=\frac{f_1+f_2+f_3+f_4+2(m_1+m_2+m_3+m_4)+4p}{16}\)

其中,\(m\) 是邊的中點,\(p\)​ 是舊頂點位置

Catmull-Clack 細分效果圖:

曲面細分技術(Tessellation)

曲面細分技術(Tessellation) 通過硬件+算法的方式來完成網格細分的操作,在不耗費CPU資源的情況下讓簡單的模型變得細節更多、表面更加光滑。

最初,Tessellation 技術僅用於網格細分。隨着DirectX11中引入可編程的Tessellation Shader后,Tessellation 技術開始多了更多的頂點插值算法來實現別的效果(例如,NVIDIA的一個Demo演示了利用Tessellation技術生產的“頭發”,在有限的頭發模型中鑲嵌入更多的頭發模型)

Tessellation 可被重新編程來用來實現如下技術(部分):

  • 網格細分(Mesh Subdivision)
  • Displacement mapping
  • 頭發鑲嵌
  • 地形渲染

在DirectX11的渲染管線中,Tessellation 技術包含了三個流程:Hull Shader、Tessellator、Domain Shader。

  • Hull Shader(外殼着色器):控制自動生成頂點的數量(Tessellator的細分級別)和算法。

  • Tessellator:根據 Hull Shader 配置好的參數,GPU硬件會自動進行鑲嵌處理。

  • Domain Shader(域着色器):修改鑲嵌后的頂點的屬性,可用於生成曲面、法線平移、Displacement mapping等。

網格簡化(Mesh Simplification)


Quadric Error 網格簡化算法(Quadric Error Mesh Simplification)

  1. 網格簡化最簡單的想法是每次簡化都坍縮(collapse)一條邊,並且:

坍縮一條邊后自然會形成一個新的頂點,這個頂點需要放在適當的位置來盡可能保持坍縮后的模型與原來的模型一致,於是便引入了一個衡量新舊模型差別的數值概念:Quadric Error Metrics。

朴素的想法是:新頂點位置使用取周圍幾個頂點的位置平均或者中點的位置,旦這樣效果顯然不佳(如圖左)。

二次誤差度量(Quadric Error Metrics):坍縮后形成的新頂點與周圍各個舊三角形所在平面的距離之和。

img
  1. 使用最小化 Quadric Error Metrics 方法(類比於機器學習里的最小二乘法)找到新頂點應當所在的位置即可。

Level Of Details 技術(LOD)

LOD 技術:簡單來說就是渲染遠處模型的時候不一定要使用原始高精度的模型,而可以使用簡化的模型來替代,從而減少提交GPU的頂點數。為了做到這種優化效果且避免低模穿幫,可以根據模型與攝像機的距離來決定模型的精度(或者說簡化程度)。

生成簡化網格的算法往往比較耗時,因此一般采用離線計算先計算出若干個Level的模型(不同簡化程度),然后在運行時根據模型與攝像機的距離來決定采用哪個Level的模型。

LOD的思想也可以應用到游戲開發的其它方面,例如一些Component的update頻率可以根據與攝像機的距離來適當減小,《刺客信條》的NPC基本上就是采用這種LOD方式,因為視野遠處的NPC即使行為稍有些粗糙滯后都很難被察覺到。

當然,這種Discret LOD是必然有突變的,level 切換的時候很難采用插值的方式實現模型過渡效果,因此也有LOD的實現是借助 Tessellation 技術:使用粗糙模型+Displacement mapping的方式,當模型距離最遠時使用原始模型,距離越近則細分程度越高。由於細分的工作是GPU去做的,因此可以大大減少因動態切換模型而導致的開銷。

參考



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM