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