ID Tech 5 中"Megatexture"針對(duì)地形的D3D9
基本實(shí)現(xiàn)原理
姚勇
H3D
2007-8
本文對(duì)ID SOFTWARE 使用的"megatexture"技術(shù),針對(duì)地表貼圖應(yīng)用的D3D9 的硬件實(shí)
現(xiàn),做了概要式的介紹。并對(duì)技術(shù)的實(shí)現(xiàn),優(yōu)化,擴(kuò)展,和實(shí)用性進(jìn)行了刨析。轉(zhuǎn)載請(qǐng)注名
作者和H3D。
一,綜述
ID TECH5是PC 3D游戲之父和DOOM之父John Carmack最新推出的一項(xiàng)新的游戲制作
技術(shù)。核心內(nèi)容為一種命名為"Megatexture"的動(dòng)態(tài)貼圖管理技術(shù)。實(shí)際上是一種動(dòng)態(tài)卸載和
裝載渲染資源的技術(shù)統(tǒng)稱。Idsoftware DOOM3引擎的lighting/shadow/shader方案統(tǒng)一以后,
同UNREAL3一樣,面對(duì)次世代游戲?qū)Y源的無(wú)窮盡需求,需要盡快建立起一種實(shí)際工程技術(shù)
方案,加快構(gòu)建3D虛擬現(xiàn)實(shí)的生產(chǎn)。
圖片來(lái)源:Quake Wars
這個(gè)技術(shù)最主要方向就是要把VR3D建造從有限的顯卡內(nèi)存中釋放出來(lái)。把美術(shù)從繁重
的貼圖重用繪制中解脫出來(lái)。因?yàn)閂R3D主要資源消耗都在貼圖上,所以這個(gè)技術(shù)主要針對(duì)
texture。同時(shí)geometry也可以作為動(dòng)態(tài)資源。一旦rendering相關(guān)資源作為動(dòng)態(tài)流進(jìn)行管理,
所帶來(lái)的另一個(gè)好處就是可以讓VR世界變?yōu)閯?dòng)態(tài)的。隨時(shí)改變texture/geometry。
總得來(lái)講,ID這項(xiàng)針對(duì)工程應(yīng)用技術(shù)主要致力于解決:1-3DVR資源需求的爆炸增長(zhǎng)和
有限顯卡顯存的矛盾;2-美術(shù)資源需求的爆炸增長(zhǎng),以及生產(chǎn)力低、成本高昂的矛盾
在ID TECH5演示中,實(shí)時(shí)演算播放了一個(gè)細(xì)節(jié)非常豐富的室外地形,同時(shí)結(jié)合了一個(gè)
小型的室內(nèi)場(chǎng)景。所有模型和貼圖制作,按照Carmack介紹,只讓幾個(gè)美術(shù)花了4天時(shí)間。
就制作出20G的游戲美術(shù)資源。而游戲引擎負(fù)責(zé)把幾十G的資源動(dòng)態(tài)裝載到顯卡進(jìn)行渲染。
本文就以下幾個(gè)問(wèn)題做初步講述:1,綜述地形渲染以及貼圖技術(shù);2,Clipmap介紹;
3,基于D3D9的解決方案描述;4,優(yōu)化和擴(kuò)展;5,方案可行性
1-1
,
Mega
Texture
Megatexture 的具體實(shí)現(xiàn),在DOOM3 中的地形繪制已經(jīng)加入。具體實(shí)現(xiàn)細(xì)節(jié)簡(jiǎn)單描述
如下:
DOOM3 的地形貼圖最大支持32768x32768 。即5.46 G。在DOOM3 中,以128x128
大小的塊進(jìn)行儲(chǔ)存便于快速讀取。以最大2048x2048 的clipmap 尺寸進(jìn)行處理。其實(shí)可以計(jì)
算出在D3D9 標(biāo)準(zhǔn)的顯卡上,normalmap+6 clipmap stack 的最大理論支持貼圖數(shù)據(jù)大小為
(2048 * 2^6 )^2 *4= 68T bytes. 這個(gè)大小針對(duì)現(xiàn)在的PC 硬盤是綽綽有余的。
DOOM3 使用這張全局metatexture 紋理渲染地形,不使用LOD,GEOM-MORPHING。
1-2
,
傳統(tǒng)
地形貼圖渲染
當(dāng)使用Tiling 方式繪制貼圖,等于把貼圖圖素(texel)密度成倍擴(kuò)大。以重復(fù)紋理信息量
的代價(jià)保證在一定分辨率下屏幕上貼圖的精細(xì)程度。在繪制大范圍地形時(shí),使用不Tiling 的
全局貼圖無(wú)法表現(xiàn)貼地處的地表細(xì)節(jié)。所以使用一些可以重復(fù)(Tiling)的不規(guī)則圖案的貼圖
來(lái)進(jìn)行模擬。
1-2-1
Tiling
地形貼圖
由于地形貼圖尺寸很大,所以無(wú)法使用全局貼圖。而是把多層Tiling 的紋理使用alpha
通道互相融合起來(lái)。諸如WOW[1],天堂2 等大型室外地形渲染多采用此技術(shù)。此技術(shù)在每
一層Tiling 貼圖依然用到了一張全局alpha 貼圖。以及一張全地形唯一的靜態(tài)光影貼圖。在
multitexture 中根據(jù)顯卡的multitexture 處理單元數(shù)量,進(jìn)行multi-pass 和multitexture 的混合
渲染。
比如,混合綠草,土路,野花的一塊室外地形,需要至少3 層地表貼圖。分別是一塊
256x256 的草貼圖,128x128 的土路貼圖,和128x128 的野花貼圖。每層紋理使用Tiling 模
式進(jìn)行繪制,在繪制的同時(shí),每層紋理帶有一張ALPHA 灰度圖(第一層不用)。用來(lái)表明
本層紋理在融合中所占的比重。把3 張地表貼圖,2 張ALPHA 貼圖,以及一張LIGHTMAP
貼圖混合起來(lái),就有如下地表效果。可以看出土路和草地之間的均勻過(guò)渡。
圖片來(lái)源:H3D
如果進(jìn)行優(yōu)化,4 層ALPHA 可以混合稱為一張貼圖。Lightmap 一張。那么也至少需要
2 張全局貼圖進(jìn)行地表繪制。
1-2-2
全局地表紋理混合Tiling
細(xì)節(jié)貼圖[2]
在更大廣度的地形渲染,有時(shí)候需要一種更加快速的方法。在FAR CRY 引擎中,使用
了這個(gè)技術(shù)。簡(jiǎn)單描述為,使用一張全局地表紋理,渲染地表所有植被和光影信息。在離視
點(diǎn)近的范圍內(nèi),使用一張表現(xiàn)當(dāng)?shù)氐乇砑?xì)節(jié)的貼圖,以Tiling 方式進(jìn)行融合疊加。這樣在細(xì)
節(jié)度上,以Tiling 方式的貼圖以高細(xì)節(jié)圖素紋理,掩蓋了下面那一層全局貼圖的粗糙顆粒。
總的來(lái)講,分層Tiling Alpha 混合地表貼圖,和全局地表混合Tiling 細(xì)節(jié)貼圖,兩種方
法都是靠貼圖的Tiling 來(lái)增大視點(diǎn)附近貼圖圖素的密度。防止比屏幕分辨率小的2 圖素之間
進(jìn)行線性差值。影響真實(shí)感。
二,Clip
maps
基本介紹
針對(duì)受顯卡顯存制約,無(wú)法使用大尺寸貼圖進(jìn)行繪制,1998年SGI公司發(fā)表了一篇名為
<The Clipmap: A Virtual Mipmap>[3]的論文。論文里詳細(xì)闡述了一種以有限硬件性
能,來(lái)實(shí)現(xiàn)相對(duì)無(wú)限大貼圖的渲染。論文是一整套硬件與軟件結(jié)合的方案。它可以實(shí)現(xiàn)以一
平方米一個(gè)圖素,用單一貼圖進(jìn)行整個(gè)地球表面的渲染。并且結(jié)合硬件數(shù)據(jù)傳輸帶寬,以及
相應(yīng)優(yōu)化方法,魯棒的保證以任意速度漫游時(shí)保持在60Hz(針?biāo)俾剩O旅嫦葘?duì)此技術(shù)做一定
簡(jiǎn)要介紹。在第三節(jié)給出基于D3D9硬件的解決方案思路。下圖為Clipmap實(shí)現(xiàn)的美國(guó)國(guó)家地
圖實(shí)時(shí)漫游的一小部分。美國(guó)約塞米蒂國(guó)家公園(Yosemite National Park)南部的一半。整個(gè)
美國(guó)使用一張170G的貼圖。在顯卡中的clipmap貼圖緩存為16M。這個(gè)貼圖內(nèi)存用量在今天
的PC硬件上是完全可以實(shí)現(xiàn)的。
圖片來(lái)源:<The Clipmap: A Virtual Mipmap>
2-1
,
Mipmap
工作原理及其分析
我們先從mipmap[4]工作原理分析開(kāi)始。如圖:
圖片來(lái)源:<The Clipmap: A Virtual Mipmap>
Mipmap 的工作原理是,把一張貼圖按照2 的倍數(shù)進(jìn)行縮小。直到1X1。把縮小的圖都
儲(chǔ)存起來(lái)。在渲染時(shí),根據(jù)一個(gè)象素(pixel,注意pixel 和texel 區(qū)別。Pixel 是屏幕上一個(gè)點(diǎn)。
Texel 是貼圖上一個(gè)圖素)離眼睛位置的距離,來(lái)判斷從一個(gè)合適的圖層中取出texel 顏色賦
給象素。D3D 和OGL 都有想對(duì)應(yīng)的API 控制接口。如下圖
圖片來(lái)源:<The Clipmap: A Virtual Mipmap>
通過(guò)觀察mipmap 工作原理我們可以發(fā)現(xiàn),硬件總是根據(jù)眼睛到目標(biāo)的距離,來(lái)選取最
適合當(dāng)前屏幕象素分辨率的圖層。假設(shè)有一張32768x32768 mipmap 貼圖。當(dāng)前屏幕分辨率
為1024×1024。眼睛距離物體比較近時(shí),mipmap 最大也只可能從1024×1024 的mipmap
圖層選取texel。再次,當(dāng)使用三線性過(guò)濾(trilinear)時(shí),最大也只訪問(wèn)到2048x2048 的圖層選
取texel,來(lái)和1024x1024 圖層中的圖素進(jìn)行線性插值。
這樣一個(gè)基本事實(shí)告訴我們,在使用任何尺寸貼圖渲染任意距離的物體時(shí),貼圖采樣只
會(huì)用到不大于屏幕分辨率2 倍的mipmap 層。根據(jù)這個(gè)事實(shí),我們可以創(chuàng)建clipmap 對(duì)大尺
寸貼圖進(jìn)行渲染時(shí)的優(yōu)化。
2-2
,
Clipmap
原理
2-2-1
Clipmap
構(gòu)建
在原始clipmap 論文中,clipmap 在顯卡內(nèi)存中的構(gòu)建如圖:
圖片來(lái)源:<The Clipmap: A Virtual Mipmap>
Clipmap Pyramid(clipmap 棱椎)是我們PC 顯卡中常見(jiàn)的mipmap 形式。Clipmap Stack
是不同于mipmap 實(shí)現(xiàn)的地方。橫線繪制的棱錐代表完整貼圖的mipmap 形式。但是在顯存
中,大于clipmap Pyramid 最高層尺寸的貼圖,都以clipmap pyramid 尺寸存放,但是相應(yīng)的,
clipmap stack 中的貼圖代表的原始貼圖面積,一層比一層小。比如clipmap pyramid 最大
2048x2048。在之上一層,mipmap 表達(dá)是4096x4094 圖素。在clipmap stack 中,還是儲(chǔ)存
2048x2048 大小的貼圖。顯然此代表的就是mipmap 尺寸4096 的一半邊長(zhǎng),即原始面積的
1/4大小。依次推上去,每層都是下層代表面積的1/4。Clipmap pyramid最大邊長(zhǎng)即為Clip
size
。
Clipmap 貼圖的中心點(diǎn),在整張貼圖的位置坐標(biāo),我們稱為ClipCenter
。ClipCenter 由
當(dāng)前攝像機(jī)在整個(gè)世界中的相對(duì)位置來(lái)決定。
實(shí)際中,目前D3D9 級(jí)別的PC 顯卡硬件并不支持這種儲(chǔ)存形式的mipmap。具體實(shí)現(xiàn)
方法將在第三章講解。
2-2-2
渲染Clipmap
在渲染中,針對(duì)一個(gè)Pixel,根據(jù)當(dāng)前Pixel,找到相應(yīng)的clipmap 層,如果處于clipmap
pyramid,直接按照mipmap 傳統(tǒng)方式采樣取圖素。如果處于clipmap stack,則把貼圖坐標(biāo)根
據(jù)當(dāng)前clipmap stack 代表整體面積的比例,進(jìn)行縮放,得到對(duì)應(yīng)位置圖素。這樣就可以正確
渲染屏幕上的任意物體。如下圖:
圖片來(lái)源:<The Clipmap: A Virtual Mipmap>
把CLIPMAP 所有圖層繪制出來(lái),從正上方看,就是象北京二環(huán)內(nèi),二環(huán),三環(huán),四環(huán)
為分割。繪制中心區(qū)域的貼圖分辨率最大,但是代表的面積最小。繪制最外圍四環(huán)之外的貼
圖分辨率最小。是因?yàn)榈搅薱lipmap pyramid 層,一層就代表一張全局貼圖。但是分辨率已
經(jīng)被縮小了很多倍。而分辨率最大的clipmap stack 頂層,由于尺寸必須保持clipmap pyramid
的最大尺寸,所以所代表的面積就小了很多。這種折中正是由于基于繪制屏幕上的任何物體
都不可能使用大于屏幕分辨率的貼圖尺寸,所以在顯存中只提供剛剛滿足繪制在一針內(nèi),從
一個(gè)視點(diǎn)看過(guò)去的所有場(chǎng)景(地形)分辨率的貼圖內(nèi)容。
2-2-3
clima
p
LOD
計(jì)算以及每層貼圖坐標(biāo)計(jì)算
給定一個(gè)根據(jù)ClipCenter換算過(guò)的貼圖坐標(biāo),下面需要計(jì)算出在屏幕上的一個(gè)物體的象
素,從clipmap中選取一層,索引貼圖圖素。由mipmap LOD(LOD數(shù)在本文用俗稱層數(shù)描述)
計(jì)算公式得知,clipmap LOD計(jì)算和mipmap一樣。并且可以保證任意pixel計(jì)算出來(lái)的climap
層必然落在clipmap stack中。一般PC 3D顯卡硬件計(jì)算都采用Heckbe算法。簡(jiǎn)單描述如下:
LOD = log2[f(x, y)]; f(x,y)為屏幕x,y軸方向貼圖坐標(biāo)變化率的最大值。貼圖坐標(biāo)變
化率計(jì)算由屏幕象素X,Y坐標(biāo)分別遞進(jìn)一個(gè)象素單位的變化投影到貼圖坐標(biāo)系得出。具體描
述參考[5]。
2-3
,存儲(chǔ)效率
Clipmap由于采用clipmap stack和clipmap pyramid結(jié)合的方式,使用clipsize為2^m的
clipmap,把一張2^n邊長(zhǎng)貼圖容量從(4n+1 - 1)/3 字節(jié)下降為4m(n - m + 4/3) - 1/3 字
節(jié)。更具體的數(shù)據(jù)如下:
類型/邊長(zhǎng)512 1024 4096 32768 67108864
Full Mipmap 682KB 2.7MB 42.7MB 2.7GB 10923TB
512 Clipmap 682KB 1.1MB 2.2MB 3.7MB 9.1MB
1024 Clipmap 682KB 2.7MB 6.7MB 12.7MB 34.7MB
2048 Clipmap 682KB 2.7MB 18.7MB 42.7MB 131.7MB
可見(jiàn)clipmap極大降低了顯卡內(nèi)存對(duì)渲染超大容量貼圖的要求。目前D3D9的主流顯卡從
128M到256M不等。在1024的Clipsize下,幾乎所有顯卡都可以滿足要求。
2-4
,繪制整個(gè)地球表面的方案
--
虛擬
clipmap
(簡(jiǎn)述)
當(dāng)繪制國(guó)家或者星球表面這樣規(guī)模的實(shí)時(shí)渲染時(shí),整張貼圖尺寸為2^26 的平方。這樣
一來(lái),需要在顯卡硬件內(nèi)部計(jì)算的工作,諸如貼圖坐標(biāo)換算等都難以在精度為IEEE 32
FLOAT 下正確進(jìn)行。
在原有clipmap 基礎(chǔ)上,在U,V 方向加入一個(gè)坐標(biāo)偏移向量。在clipmap stack 的縱向方
向,加入一個(gè)偏移數(shù)值。形成如下圖解構(gòu):
圖片來(lái)源:<The Clipmap: A Virtual Mipmap>
系統(tǒng)只要能夠保證從圖中的3 種情況中正確尋址,就能夠保證超大貼圖的clipmap 渲染。
三,基于D3D9
的簡(jiǎn)化實(shí)現(xiàn)
從之前對(duì)Clipmap 的描述中可以看出。現(xiàn)代D3D9 顯卡具備了渲染clipmap 的大部分功
能。唯一欠缺的是clipmap stack 的模擬。因?yàn)閏lipmap pyramid 就是一張標(biāo)準(zhǔn)的mipmap 貼
圖。所以D3D9 只要能夠把clipmap stack 模擬出來(lái),使用shader model3 可以很容易的實(shí)現(xiàn)
clipmap。
3-1
,
Multitexture
我們利用顯卡硬件的multitexture 模擬clipstack。這是D3D9 簡(jiǎn)化實(shí)現(xiàn)的最基本思想。
PC 顯卡支持clip pyramid。在pixel shader 中,如果想利用clipmap stack,就必須有某種途徑
讓pixel shader 使用除了clip pyramid 之外的貼圖。自然我們想到了使用multitexture。D3D9
標(biāo)準(zhǔn)顯卡應(yīng)該支持最少8 層紋理單元(不支持的硬件很快會(huì)絕跡,所以可以不考慮)。假設(shè)
我們不使用法線貼圖進(jìn)行凹凸象素光照。
使用第8 層裝載clip pyramid,使用2048x2048 32bit DDS 貼圖。從第一層到第七層我們
都可以使用clip stack 貼圖。這樣,分別裝載4096, 8192, 16384,32768,65536,131072,262144 邊
長(zhǎng)mipmap 的clipmap。每一層占用2048x2048*4*/4*1.33 /1024 /1024 = 5.32Mb 。這樣一共8
層貼圖總共43MB 貼圖顯存,可以容納一張274TB 的貼圖。當(dāng)我們使用每層1024×1024
貼圖時(shí),使用12MB 顯存就可以模擬68TB 的貼圖。顯然對(duì)于游戲來(lái)講綽綽有余。注意這
里只是簡(jiǎn)化計(jì)算,沒(méi)有把trilinear 考慮進(jìn)去。
3-2
,
Toroidal addressing
在第四章我們將考慮優(yōu)化和動(dòng)態(tài)管理clipmap。我們知道用MULTITEXTURE 模擬的
clipmap 只是當(dāng)前視角觀察的貼圖用量。當(dāng)攝像機(jī)移動(dòng)時(shí),clipmap 的貼圖組必須同時(shí)更新。
除了最底層clipmap pyramid 貼圖不用更新,其他幾張clipmap stack 貼圖必須根據(jù)攝像機(jī)移
動(dòng),改變ClipCenter 位置。然后從磁盤上把clipcenter 周圍的貼圖調(diào)入。這涉及到顯存寫入
問(wèn)題。可以想見(jiàn)當(dāng)所有clipmap stack 貼圖同時(shí)頻繁裝載總共十幾MB 容量的內(nèi)存,對(duì)于磁
盤IO 和顯存帶寬都是極大考驗(yàn)。所以針對(duì)clipmap 更新特點(diǎn),在貼圖尋址方面采用wrap 循
環(huán)尋址。然后對(duì)貼圖的更新采用如下方式:
圖片來(lái)源:NVSDK
3-
3,
p
ixel
shader
實(shí)現(xiàn)思想概要
由于有了第二章climpa 渲染的大概描述,以及前兩節(jié)關(guān)于clipmap stack 和貼圖尋址方
式,我們利用shader model 3 的pixel shader 功能可以直接實(shí)現(xiàn)具體算法。描述如下:
1,計(jì)算mipmap LOD。
2,計(jì)算光照
3,假如應(yīng)該采樣clipmap pyramid,直接采樣,混合光照,完成
4,假如應(yīng)該采樣clipmap stack 貼圖,重新計(jì)算貼圖坐標(biāo)
5,根據(jù)mipamapLOD 選擇相應(yīng)的stack 貼圖。采樣,混合光照,完成
首先,計(jì)算mipmap LOD。這里可以采用三線性插值。
例如:
PSOut PS_Trilinear(PSIn input)
{
PSOut output;
float2 dx = ddx( input.texCoord * g_TextureSize.x );
float2 dy = ddy( input.texCoord * g_TextureSize.y );
float d = max( sqrt( dot( dx.x, dx.x ) + dot( dx.y, dx.y ) ) , sqrt( dot( dy.x, dy.x ) +
dot( dy.y, dy.y ) ) );
// 計(jì)算出
float mipLevel = log2( d );
float blendGlobal = saturate(g_StackDepth - mipLevel);
float4 color0 = PyramidTexture.Sample( samplerLinear, input.texCoord );
If (blendGlobal)//如果使用了全局clipmap pyrimad,及早退出
{
output.color = color0;
}
Else
{//使用了clipmap stack 貼圖,計(jì)算貼圖坐標(biāo),然后動(dòng)態(tài)分支判斷應(yīng)該采樣第幾層
貼圖
// This fractional part defines the factor used for blending
// between two neighbour stack layers
float blendLayers = modf(mipLevel, mipLevel);
blendLayers = saturate(blendLayers);
int nextMipLevel = mipLevel + 1;
nextMipLevel = clamp( nextMipLevel, 0, g_StackDepth - 1 );
mipLevel = clamp( mipLevel, 0, g_StackDepth - 1 );
// Here we need to perform proper scaling for input texture coordinates.
// For each layer we multiply input coordinates by g_ScaleFactor / pow( 2,
layer ).
// We add 0.5 to result, because our stack center with coordinates (0.5, 0.5)
// starts from corner with coordinates (0, 0) of the original image.
float2 clipTexCoord = input.texCoord / pow( 2, mipLevel );
clipTexCoord *= g_ScaleFactor;
//只是簡(jiǎn)單的雙線性采樣
if (mipLevel==0)
{
//use clipStackTexture0.Sample(...)
}
If (mipLevel ==1)
{
//use clipStackTexture1.Sample(...)
}
}
Return output;
}
3-
4,
D3D10 的實(shí)現(xiàn)【
7】
D3D10 引入了一種叫Texture Array 的功能。可以在pixel shader 中直接利用一個(gè)整
數(shù)下標(biāo)來(lái)尋找所需要的貼圖,然后進(jìn)行采樣。思路同上,只不過(guò)不用動(dòng)態(tài)分支,直接進(jìn)行數(shù)
組索引后采樣。
圖片來(lái)源:NVSDK
圖中綠色部分就是texture array。
四,一些優(yōu)化和擴(kuò)展
Clipmap 在顯存中的存在,只是應(yīng)對(duì)某一個(gè)固定攝像機(jī)位置和角度的場(chǎng)景貼圖需求。當(dāng)
攝像機(jī)移動(dòng)時(shí),必須對(duì)clipmap 貼圖進(jìn)行更新。具體更新方法第三章已經(jīng)提過(guò)。但是,在攝
像機(jī)每一針運(yùn)動(dòng)都使用磁盤IO 和阻塞渲染管道的內(nèi)存搬運(yùn),是不具實(shí)用性的。所以在實(shí)用
中,必須對(duì)clipmap 動(dòng)態(tài)更新進(jìn)行高度優(yōu)化。這也是此技術(shù)的核心所在。
同時(shí),對(duì)clipmap 的一些擴(kuò)展是為了增強(qiáng)游戲的表現(xiàn)力。以下4-6 到4-9 的擴(kuò)展方面沒(méi)
有進(jìn)行任何實(shí)際論文和實(shí)例支持,只是一種對(duì)現(xiàn)有技術(shù)擴(kuò)充的預(yù)想和估計(jì)。希望專家給與更
深入的建議。
4-1
,動(dòng)態(tài)
clipmap
管理
Clipmap 的動(dòng)態(tài)管理,必須滿足幾個(gè)條件。1,攝像機(jī)移動(dòng)時(shí)的平滑實(shí)時(shí)渲染;2,不能
對(duì)攝像機(jī)的移動(dòng)速度和位置有所限制;3,動(dòng)態(tài)裝載更新應(yīng)該是外部不可見(jiàn),自動(dòng)進(jìn)行的。
4-2
,
2
級(jí)
cache
由一般異步動(dòng)態(tài)裝載卸載應(yīng)用技術(shù)得知,在大數(shù)據(jù)量進(jìn)行從磁盤到內(nèi)存的交換時(shí),必須
有足夠的緩沖。由于磁盤到內(nèi)存,內(nèi)存到顯存的帶寬大不一樣,磁盤到內(nèi)存比內(nèi)存到顯存慢
得比較多。所以,對(duì)于從硬盤到顯卡內(nèi)存的緩沖,需要存在至少2 步CACHE。
第一步,從磁盤到主內(nèi)存的緩沖。對(duì)clipmap stack 貼圖周邊的圖素,必須預(yù)先讀入一些
到主存CACHE 中來(lái)。并且這個(gè)動(dòng)作應(yīng)該在整個(gè)游戲期間保持不停頓。預(yù)先讀入的數(shù)據(jù)根據(jù)
玩家移動(dòng)方向做一定預(yù)測(cè)。
在模擬星球表面的海量貼圖庫(kù)中進(jìn)行更新,同時(shí)還要考慮不同磁盤陣列相應(yīng)速度等等。
所以磁盤到主存的緩沖策略非常重要。
第二步,從主存裝入內(nèi)存,每次更新每個(gè)clipmap stack 貼圖周邊的半圈貼圖內(nèi)容。
圖片來(lái)源:<The Clipmap: A Virtual Mipmap>
棕色區(qū)域是每次更新的內(nèi)容。
4-3
,
多線程
IO
控制
在主循環(huán)中對(duì)貼圖進(jìn)行磁盤IO,解壓,然后寫入clipmap stack 貼圖緩存,會(huì)同時(shí)阻礙
CPU 和GPU 的工作流水線。使得處理器停滯,影響效率。所以,對(duì)磁盤到主存的讀取IO,
解壓工作,可以放在另外一個(gè)線程中進(jìn)行。寫入貼圖顯存的工作由于本身會(huì)阻斷D3D9 級(jí)別
顯卡的流水線。但是,可以利用一些策略延緩一次性裝入所有CLIPMAP STACK 貼圖的并
發(fā)。這將在4-6 講解。
4-1 中提到的攝像機(jī)平滑移動(dòng)渲染,主要是指對(duì)clipmap stack 貼圖更新的步驟一定要
短,不能極大幅度影響主渲染循環(huán)的執(zhí)行。在固定帶寬內(nèi),對(duì)clipmap stack 貼圖邊帶更新的
數(shù)據(jù)量并不很大。基本可以保持一個(gè)平滑渲染的過(guò)程。
在WINDOWS 系統(tǒng),使用無(wú)緩沖的異步IO 模式是最適合此應(yīng)用的。且文件以硬盤簇大
小的整數(shù)倍放置,讀取效率最快。
4-4
,
使用
MaxTextureLOD
在4-1 中提到,攝像機(jī)以任意速度移動(dòng),都不能影響渲染的平滑。我們采用如下策略。
1,當(dāng)攝像機(jī)以設(shè)計(jì)速度移動(dòng)時(shí),clipmap 正常更新。
2,當(dāng)攝像機(jī)超過(guò)設(shè)計(jì)速度,clipmap 更新速度無(wú)法趕上攝像機(jī)移動(dòng)速度。則自動(dòng)調(diào)整
max texture LOD。Max texture LOD 的意義是clipmap 工作在最高clipmap stack 的貼圖層數(shù)。
這個(gè)參數(shù)同時(shí)影響clipmap upload 和渲染pixel shader 中stack 選取。降低最高細(xì)節(jié)stack 意
味著降低climap update 的負(fù)荷。
3 當(dāng)出現(xiàn)極端情況時(shí),所有clip stack 更新都趕不上camera 移動(dòng),則只使用clipmap
pyramid 貼圖進(jìn)行渲染。雖然圖象貼圖分辨率急劇下降,但是保證了camera 以任意速度漫游。
4-5
,對(duì)地形幾何渲染擴(kuò)展
--geometry
clipmap
參考GPU GEMS2 的geometry clipmap 介紹文章【6】。簡(jiǎn)單描述為:使用clipmap 進(jìn)行
頂點(diǎn)生成。把高度圖做為clipmap 進(jìn)行更新,然后做為vertex texture 的源。用以生成地形網(wǎng)
格。這么做的好處是,地形網(wǎng)格削減被放入了climap 的LOD 過(guò)程中。而不用CPU 做任何
額外計(jì)算工作。并且支持相對(duì)無(wú)限大地形。動(dòng)態(tài)地形改變。
4-6
,
double
clipmap
buffer
,無(wú)效邊帶
4-3 指出,使用多線程把磁盤IO 和解壓縮,可以促進(jìn)CPU 和GUP 協(xié)同工作。在對(duì)磁
盤文件進(jìn)行預(yù)讀取時(shí)有著極大好處。在對(duì)JPEG 進(jìn)行分塊讀取和REALTIME 解壓縮時(shí),可
以在多核系統(tǒng)上獲得額外的負(fù)載減輕。
Clipmap 原先的設(shè)計(jì),存在一個(gè)叫無(wú)效邊帶的技術(shù)。它可以使得SGI 硬件底層一邊渲染
一邊進(jìn)行邊帶的貼圖更新。等于是主存到顯存的第0 級(jí)CACHE。PC 和有的CONSOLE 顯
卡不具備這樣的功能。對(duì)于寫入顯存操作,都是把一張貼圖顯存LOCK 住,進(jìn)行寫入。在
這個(gè)期間此貼圖無(wú)法進(jìn)行渲染。但是受此啟發(fā),我們可以把CACHE 的粒度放為每層
CLIPMAP STACK 貼圖。結(jié)合多線程與DOULBE BUFFER 思想,方法如下:
1,在需要?jiǎng)?chuàng)建clipmap stack 貼圖時(shí),對(duì)每層貼圖創(chuàng)建一個(gè)BACK BUFFER。
2,在渲染CLIPMAP 同時(shí),多線程進(jìn)行另外一組stack texture 的更新。雖然可以預(yù)知假
如寫入一張貼圖要阻斷整個(gè)GPU 工作管道的話,但是由于多線程把一組stack texture 按順
序更新。所以避免了在主循環(huán)并發(fā)一次性更新整個(gè)stack texture array。如果顯卡可以同時(shí)渲
染和寫入back buffer 的話,則效率應(yīng)該會(huì)提高。
3,每針?shù)秩就戤叄{(diào)換STACK BACK BUFFER 到前臺(tái)。
這個(gè)方法DOULBE 了CLIPMAP 占用內(nèi)存。但是在多核環(huán)境下,尤其顯卡支持渲染時(shí)
并發(fā)寫入貼圖顯存功能的話,CLIPMAP 更新效率會(huì)大大提高。內(nèi)存的使用,前面進(jìn)行過(guò)計(jì)
算,適合游戲的貼圖,采用1024 大小的DDS CLIPMAP,顯存占用不大。
4-7
,支持非
2
的
N
次方全局貼圖
在游戲中,一個(gè)全局的世界如果只能是2 的N 次方大小,會(huì)極大限制美術(shù)工作。如果
是正方形世界,貼圖只能是4G,16G,64G(都乘1.33)這個(gè)數(shù)量級(jí)別。考慮引入MxN 大小
的貼圖。M 和N 都不是2 的冪。
我們?cè)谥先∪我庖稽c(diǎn)P,k<Px<M-k, k<Py<N-k, k=2^q(q=1,2,...),k 為接近分辨率的一
個(gè)2 的冪整數(shù)。圍繞P 建立一個(gè)邊長(zhǎng)為k 的正方形。以k 正方形為基礎(chǔ),創(chuàng)建clipmap。這
個(gè)clipmap 代表在P 點(diǎn)繪制需要的貼圖內(nèi)容。
隨著攝像機(jī)移動(dòng),原先不用更新的clipmap pyramid 也需要根據(jù)ClipCenter 移動(dòng)進(jìn)行更
新。保持貼圖棱錐還是以2 的冪進(jìn)行更新。換句話說(shuō),除了clipmap stack 貼圖更新,clipmap
pyramid 貼圖以及其mipmap 層,都需要更新。
這樣一來(lái),我們就可以用clipmap 進(jìn)行任意長(zhǎng)寬世界貼圖的渲染。
4-8
,
支持法線貼圖進(jìn)行象素級(jí)別光照
在ID TECH5 演示中,地表都具有凹凸貼圖象素光照。在這里無(wú)法給出確切的實(shí)現(xiàn)方法。
只是嘗試列出可能的實(shí)現(xiàn)方案。希望更進(jìn)一步的探討。
法線貼圖同樣使用一張全局貼圖。
1, multipass 方法。使用第二張clipmap 裝載法線貼圖。
2, 在更新diffuse color clipmap 時(shí),利用3 張clipmap stack 貼圖的ALPHA 通道,
裝載法線貼圖的z,y,z。或者只裝載x,y(在pixel shader 計(jì)算z)。然后在pixel shader
重組,進(jìn)行光照計(jì)算。2 層stack clipmap 代表一層normalmap。我們只在近距離使用
normalmap,遠(yuǎn)處就用一個(gè)RGB(0.5,0.5,1)的藍(lán)色象素代替。在超出clipmap stack 視野區(qū)
域使用mipmap 的trilinear 插值。
3, 使用clipmap 其中的一層或者兩層裝載法線貼圖,因?yàn)檫h(yuǎn)距離地形景物不需要象素
級(jí)別的光照。所以直接對(duì)近景進(jìn)行象素光照即可。凹凸象素光照消失的地方使用一些三線性
插值,平滑過(guò)渡。
4-9
非地形應(yīng)用
Clipmap 主要用于大規(guī)模地形渲染的貼圖調(diào)度。在此基礎(chǔ)上,對(duì)非地形場(chǎng)景的渲染,應(yīng)
用clipmap 也稱為可能。Clipmap 實(shí)際是對(duì)貼圖數(shù)據(jù)庫(kù)進(jìn)行了一種線性組織和查找。可以根
據(jù)簡(jiǎn)單的x,y 坐標(biāo)以及u.v 貼圖坐標(biāo)定位所需要貼圖在clipmap texture database 的位置。地形
應(yīng)用的天然方便之處在于,地形網(wǎng)格的空間位置本身就說(shuō)明了其貼圖紋理在clipmap texture
database 中的位置。
根據(jù)此思想,如果能夠在場(chǎng)景中固定幾何物體信息中標(biāo)致好所在clipmap 數(shù)據(jù)庫(kù)中的位
置。并且有效組織場(chǎng)景中的幾何體貼圖存放位置也和其世界空間位置相關(guān)。這樣就能在幾何
體與clipmap 之間建立起一種聯(lián)系。隨著攝像機(jī)的移動(dòng),clipmap 貼圖不斷更新,相應(yīng)場(chǎng)景
中的物體就被賦上材質(zhì)。當(dāng)視角遠(yuǎn)離物體,此物體貼圖不再被使用,從顯存中清除。這樣就
實(shí)現(xiàn)了非地形的海量幾何物體貼圖的clipmap 管理。
此思想只是停留在思考階段。需要在今后的工作中實(shí)踐。
五,是否值得
5-1
,地形渲染精度和容量
我們來(lái)計(jì)算一下實(shí)際游戲大概需要的貼圖容量。
假設(shè)地形,高度圖的一個(gè)象素代表一個(gè)格子。一個(gè)格子代表現(xiàn)實(shí)一米。屏幕分辨率
r=1024x1024。人眼離地面最低距離d=1 米。FOV=90。離地面最近距離為人眼直視下方。根
據(jù)透視關(guān)系,可以推算出在屏幕上2 米的格子將會(huì)撐滿整個(gè)屏幕。
一張非TILING 的貼圖,平鋪在地下,我們可以計(jì)算出,如果需要屏幕的一個(gè)象素恰好
被一個(gè)貼圖圖素覆蓋(mipmapLOD=0)。則需要2x2 的格子貼一張1024 非TILING 的貼圖。
對(duì)于一個(gè)格子貼512 象素才不會(huì)被filter 進(jìn)行插值模糊。這個(gè)貼圖細(xì)節(jié)度是非常驚人的。
按這個(gè)計(jì)算, 要一張全局RGB24BIT 貼圖貼滿1 平方公里的區(qū)域, 就需要
1024*1024*512*512*3*1.33 字節(jié)= 1Tb 的RGB 貼圖。粗略估計(jì)JPEG 大概為40-50G 之間。
但是1T 的海量貼圖相當(dāng)于一張1024x1024 圖的26 萬(wàn)倍,這基本不太可能由美術(shù)手工完成。
而且,一公里的距離根本不足以表現(xiàn)大型世界。假設(shè)人站在512,512 的坐標(biāo),500 米的直
線距離,景物遠(yuǎn)遠(yuǎn)沒(méi)有達(dá)到人眼視界之外。人眼在晴天看遠(yuǎn)處山脈可以有十幾公里的視界。
就算在遠(yuǎn)處不用精細(xì)的貼圖,但是人既然能夠移動(dòng)過(guò)去,那么必然要制作這么大范圍的全局
貼圖。利用512 象素代表一米顯然是不現(xiàn)實(shí)的。
如果我們認(rèn)為不需要那么高的精度。觀察WOW,粗略估計(jì)可以接受的精度為,128-256
象素代表一米(WOW 基本為256)。我們計(jì)算人眼離地1 米時(shí)一個(gè)圖素覆蓋4 個(gè)象素插值的
情況:128*128*1024*1024*3*1.33 = 65G. JPEG 估計(jì)3G。4 平方公里就是48G。
對(duì)于付出如此巨大代價(jià),在一平方公里之內(nèi),讓美術(shù)進(jìn)行了相當(dāng)于一萬(wàn)六千多張
1024x1024 地圖的手繪,實(shí)時(shí)渲染進(jìn)行非常復(fù)雜的CACHE 和多線程異步操作,得到的效果
只是4 個(gè)象素模糊一個(gè)圖素的圖形細(xì)節(jié)。而且如果游戲想承載4 平方公里的地域,基本就已
經(jīng)超出目前CONSOLE 和PC 能夠接受一個(gè)游戲容量的范圍。即便是藍(lán)光,也快到達(dá)了極限。
而4 平方公里對(duì)次世代游戲來(lái)說(shuō),簡(jiǎn)直是九牛一毛。有很多游戲(CRYSIS)對(duì)于表現(xiàn)幾十
平方公里都已經(jīng)非常得心應(yīng)手。數(shù)量也在幾個(gè)G 之內(nèi)。所以單純使用clipmap 實(shí)現(xiàn)連續(xù)大型
地形渲染,以目前硬件容量,還是比較吃力。需要其他優(yōu)化手段配合。
接下來(lái)計(jì)算貼圖更新速度需求。假設(shè)人類行走1.5 米/秒.如果按照斜前方行走。1 米128
圖素。Clipmap 為1024。Clipmap stack 為6 層。在一秒人類行走經(jīng)過(guò)的地域,以1024 為邊
界,正方形邊帶圖素個(gè)數(shù)大約為1.5/sqrt(2) *128* 1024 * 2 = 2172Kb。1 秒鐘需要更新的
圖素內(nèi)存為6x2172x3 = 39096Kb 。大約40MB。假設(shè)30Hz 刷新,一針里更新的數(shù)據(jù)為
39096/30 = 1.3Mb。一針一MB 的數(shù)據(jù)流量,也是非常客觀。
5-2
,對(duì)傳統(tǒng)地形渲染方法進(jìn)行
STREAMING
5-1 節(jié)對(duì)使用全局貼圖進(jìn)行大范圍渲染的數(shù)量和最小貼圖傳輸量做了估計(jì)。接下來(lái)我們
看一下,應(yīng)用clipmap 思想,傳統(tǒng)地形渲染方法是否有可擴(kuò)展的空間。
在1-2-1 和1-2-2 使用tiling 的兩種地形渲染方法中,都提到要應(yīng)用至少1-2 張全局地
表紋理貼圖。在使用全局貼圖繪制過(guò)程中,完全可以借鑒clipmap 的技術(shù)。把全局alpha 和
lightmap,或者全局diffuse 顏色圖放入clipmap 管理。由于其他圖層都是靠tiling 實(shí)現(xiàn)。理
論上可以實(shí)現(xiàn)貼圖密度無(wú)限制,貼圖大小無(wú)限制的全面解決方案。而制作全局diffuse 顏色
圖和制作clipmap 全局圖一樣。Alpha map 靠手工繪制。Lightmap 可以自動(dòng)生成。并不會(huì)比
只使用一張全局地形貼圖麻煩多少。
六,結(jié)論
Clipmap 極大的釋放了顯存限制,把應(yīng)用對(duì)貼圖細(xì)節(jié)的無(wú)限增長(zhǎng)需求轉(zhuǎn)化為對(duì)clipmap
實(shí)時(shí)更新的技術(shù)解決方案。此應(yīng)用不僅可以用于大規(guī)模地形渲染,也可以應(yīng)用與大型場(chǎng)景中
固定幾何物體的貼圖管理。
Clipmap 可以做為一種空間和貼圖數(shù)據(jù)庫(kù)的對(duì)應(yīng)管理系統(tǒng)。并且在象素級(jí)別進(jìn)行LOD。
結(jié)合geometry clipmap 的應(yīng)用,可以相對(duì)提高虛擬現(xiàn)實(shí)制作的生產(chǎn)力。
同時(shí)Clipmap 的更新成為了一個(gè)新的瓶頸。在PC 硬件架構(gòu)上,需要極大精力進(jìn)行更新
的優(yōu)化。
另外,在對(duì)次世代游戲質(zhì)量和渲染精度的標(biāo)準(zhǔn)下,對(duì)clipmap 采用全局世界紋理的可行
性做了分析,并提出了質(zhì)疑。同時(shí)結(jié)合傳統(tǒng)地形渲染方法,給出了與clipmap 相結(jié)合的可能
性。
來(lái)信請(qǐng)給puzzy4d@yahoo.com.cn,歡迎討論。
索引
【1】WORLD OF WOLFCRAFT,http://www.wowchina.com, Blizzard,2004
【2】Far Cry, http://www.crytek.com/, Crytek,2007
【3】<The Clipmap: A Virtual Mipmap>,Christopher C. Tanner, Christopher J. Migdal, and Michael
T. Jones,Silicon Graphics Computer Systems,1998
【4】EWINS Jp,WALLER MD,WHITE M,et a1.MIP—Map Level Selection for Texture
Mapping[J].IEEE TRANSACTIONS ON VISUAIAZATION AND COMPUTE R GRAPHICS,
1998,4(4)
【5】Mipmap 映射技術(shù)中d 值計(jì)算方法的探討,韓慧健,徐振中,張誠(chéng)潔,計(jì)算機(jī)應(yīng)用,第
24 卷第12 期,2004
【6 】Terrain Rendering Using GPU-Based Geometry Clipmaps,<GPU GEMS 2>,
Hoope,NVIDIA,2005
【7】NVIDIA, SDK10,clipmaps
http://wenku.baidu.com/view/d20b147e5acfa1c7aa00cc42.html