遊戲引擎是否支持矢量貼圖?

現在的遊戲引擎支持的都是點陣圖,有沒有考慮過支持矢量圖呢? 如果支持矢量圖的話會不會對現在的LOD(Level of Detail)技術有影響?有這方面的研究或者資料嗎?多謝!

純腦洞的一個問題。


除了帶符號距離場(signed distance field)[1] 那種方式外,以我所知目前的商業遊戲引擎沒有直接支持「矢量貼圖」。

所謂「矢量貼圖」,我認為一般應該是指由一些幾何形狀(直線、曲線、多邊形等)所組成的圖形,和傳統貼圖的分別在於有無限的解析度。作為貼圖,最重要的是對其採樣,例如二維貼圖是f : mathbb{R}^2 
ightarrow mathbb{R}^n 這種形式(如 mathbb{R}^n 是 RGB 顏色)。換一個角度想,這如同像光線追蹤,給定一個屏幕坐標,採樣該坐標的顏色。

像 SVG 這種矢量格式,要對其採樣,最壞情況下性能與路徑數目成正比,而且對曲線樣條採樣(計算點與曲線的距離)並沒有閉合解,性能會很低。

所以問題主要在於,尋找一個適合快速採樣的矢量貼圖表示方式(representation)。例如二維的三角形網格(加上 kd-tree 等加速結構),由 SDF 組成的 CSG 等。從 PowerVR GR6500 提供硬體光線追蹤功能可知,以硬體對三角形網格採樣是可行的,但其性能以及實際上這需求是否存在還有待驗證。如果只是想實驗一下,我覺得用程序做是最簡單的,在 Shadertoy 上任意一張圖片(動畫)都是可當作貼圖,實時採樣。

例如這些像二維矢量圖的 shader:

Flower at night by yibojiang

Scottish Tartan Pattern by Hanley

把上面的 shaders 作為貼圖:

然而,另一個問題是過濾,傳統貼圖可通過預生成 mipmap 來做預過濾,減少 aliasing,矢量貼圖要實現過濾可能更困難。[1] Green, Chris. "Improved alpha-tested magnification for vector textures and special effects." ACM SIGGRAPH 2007 courses. ACM, 2007.


能,辦法有的是。

最早看到的,是2006年的Beyond the pixel: towards infinite resolution textures http://staffwww.itn.liu.se/~stegu/GLSL-conics/GLSL-conics.pdf。在當年的GPU和只有GLSL的情況下,就已經能在shader裡面用cone和平面求交的方法硬算矢量紋理了。

更實際一點的,是用signed distance field。Valve那篇著名的Improved Alpha-Tested Magnification for Vector Textures and Special Effect http://www.valvesoftware.com/publications/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf 說的就是這事。用SDF還有一個好處,你可以用marching cubes的方法還原出幾何。

這方面也有SIGGRAPH級別的學術論文。2012年的Diffusion Curve Textures for Resolution Independent Texture Mapping http://research.microsoft.com/en-us/UM/people/stevelin/papers/siggraph12sun.pdf,就是用GPU求解diffusion equation的方法,做更通用的矢量紋理。

最簡單的其實是NVIDIA提供的一個OpenGL擴展GL_NV_path_rendering https://www.opengl.org/registry/specs/NV/path_rendering.txt。直接用就是了。也有相關的論文 http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/opengl/gpupathrender.pdf 和代碼 https://developer.nvidia.com/nv-path-rendering。


矢量圖本質上是一些幾何形狀,所以轉化成三角形繪製,遊戲引擎就可以支持,如最知名的UI中間件Scaleform,就是flash矢量圖在遊戲中最典型的應用。

但是一般意義上的矢量圖都是2D的,包含了幾何拓撲結構,等同於3D中的Mesh,類比一下我們可以說3D Mesh就是矢量圖,LOD就跟傳統做法一樣。比如這個純頂點色(無貼圖)做成的場景:

從樓主的問題來看,應該是想把矢量圖貼到模型上?如果只是一個方形平面的話是支持的,參考Scaleform。如果是不規則Mesh,這樣其實會改變2D矢量圖的幾何拓撲結構,目前的渲染管線是不支持的,需要自己在CPU上進行計算,效率低複雜度高,沒有性價比。


偽裝成小白的pm?!


這個腦洞和我的很像。
思路無非是分兩級,用分tile加一次粗略的繪製減小每個像素測試自己屬於哪個圖元的次數。
我印象里的nv-path的實現比較有代表性,因為那篇paper我找不到了,所以已經無法區分自己的腦補和nv-path的做法:首先將屏幕分成若干tile,每個tile是一個容器(比如16x16)。

然後先遍歷線條在tile陣列上粗繪,繪製一個線條或者就是給每個經過的tile容器加入自己的引用,這一步要用到uav。對每個小格子的繪製需要要原子操作比較費時,不過格子一共就幾千個,也不會太慢。畫完了可能需要對格子內深度排序
接著在每個格子里對每個像素進行測試:

最後一步對應的每像素操作大概是這樣:

PSOutPut PSMain(x, y)//x y為當前像素坐標
{
PSOutPut ret;
foreach(v in cells[int(x / 16)][int(y / 16)] )//不用擔心foreach步數太多,shadertoy上遍歷幾十步找一個像素很常見,那是從全屏空間而不是一個tile里找。
if(v.getpixel( vec2(x,y),ret))
return ret;

discard;
}

圖形是矢量,那麼getpixel 這一步就是用一個公式檢查當前像素是否在圖元上,比如一個圓
class circle
{
PSOutPut outv, center,r;
bool getpixel(p,ret)
{
if(length(p-center) &< r)
{
ret = outv;
return true;
}
return false;
}
};

概念就是這樣,優化空間主要是在第一步是把複雜圖元拆成基本曲線的組合,用什麼曲線請參考GPU gems3 ch25。
因為人眼就能區分尖的圓的平的,所以第一步能拆分圖元為簡單圖元的話,一種曲線公式應該夠用

可以優化的地方包括,從前向後繪製,在第一步就做遮擋判斷剔除。
小格子里用本地變數 (openCL的local,CUDA的 __share__,dx的groupshared)放顏色,深度緩衝區,加快讀寫速度,完事兒整塊提交給RT。現在顯卡每個workgroup應該有16k空間,放16x16一小塊個問題不大。
------------------------------------
找到那篇論文了,不是nvpath的:
Random-Access Rendering of General Vector Graphics
Diego Nehab Hugues Hoppe
Microsoft Research


直接在抽取紋素就可以獲得矢量圖的方法我沒腦補出來
我不太了解2d矢量圖的數據結構,如果給定在平面上任意精度的浮點數坐標,
都能很快得到當前位置處的顏色數據,並且時間複雜度還是常數級別的
類似求y=f(x)這樣的,那是沒問題

另外一種方法是可以根據視點和物體的位置實時把矢量圖生成適當大小的點陣圖紋理
然後就可以當做普通的紋理去進行過濾抽取紋素了
就可以在結果上具有矢量圖&<放大後不會模糊&>的特性
上述用cpu去算演算法上沒問題,flash就是現成的演算法不是么,但是效率是個大問題
一來cpu要實時的算這些紋理,二來還要實時的將這些紋理數據傳送到顯存,大大增加匯流排帶寬壓力,感覺不是很現實
GPU上可視化2d矢量圖的演算法我不清楚,但是按照樓上的說法&姑且認為可行吧
好處就是可以直接用已有的管線,並且用已有的紋理過濾單元(硬體),現代硬體上的利用率比較高的
感覺&<矢量貼圖&>的一個用途可能是卡通渲染,通常所說的3渲2,渲染出日漫風格
現階段卡通渲染因為紋理過濾導致的模糊以及線條物體遠近導致線條粗細的變化真是不能忍


推薦閱讀:

Paradox是怎樣的一個公司?
即時戰略遊戲中實用的尋路演算法都有哪些,比較如何?
做遊戲的人會不會有罪惡感?
ps4比ps3強多少?
計算機底層是如何訪問顯卡的?

TAG:遊戲開發 | 遊戲引擎 | 遊戲編程 |