概述
三維場影裡的天空並不是“真正”的天空,而是用圖片拼起來的,欺騙我們眼睛。通常把大家所在的情境用一個幾何體包裹起來,再在裡面貼上從各個角度的風景圖,就好像一個真正的環境一樣。想想CS之類的天空,是不是有點印象?
原理
現在的遊戲裡可能半球用的較多吧?不過原理上一樣,我們這裡以立方體為例。最簡單的方法,莫過於畫6個正方形,分別為它們貼上紋理。(要是真這樣,我就不用寫了-_-)這裡我們只用一個正方形,也只用一個紋理,HOHO~想知道怎麼回事?住下看吧(欠扁)
立方體環境貼圖(Cubic Environment Mapping),也叫立方體貼圖,就是一個紋理包含了包圍物體情境的映像資料, 就像一個物體在立方體中心一樣.每個麵包含橫豎各90度的視野,每個立方體貼圖共6個面. 面的方向如下面左圖所示:
右圖呢,就是立方體貼圖的UV座標紋理的等價形式,說到底,就是把6張圖片拼到一塊兒去了而已。不過一般情況下,立方體貼圖是映射到一個曲面上,而且,它跟本不使用UV座標。代替它的是一個3D向量,在DirectX中是D3DFVF_TEXCOORDSIZE3類型。這樣就很易的根據表面法向量將周圍環境映射到物體表面,實現反射效果(激動人心呢)。
製作立方體貼圖
看起來立方體貼圖挺麻煩的,其實DirectX自己的紋理格式.dds就支援Cubemap Texture。建立也不需要什麼複雜的工具,用SDK帶的DxTex.exe就可。
1. 建立一個立方體貼圖
2. 選擇一個表面
3. 為當面表面添加紋理
在這之前可要把各個方向的貼圖準備好哦
4. 重複2、3,直到6個面全部完成
5. 儲存
繪製天空盒子
既然有了立方體貼圖,那麼是不是畫個立方體把圖貼上就行了?道理是不錯,只不過還有更簡單的辦法:在面前畫個矩形,你往哪看,就畫哪個角度的天空!(太賤了,這樣的鬼點子是誰想的?)
還記得D3DFVF_XYZRHW不?當頂點結構體中有RHW時,表示這個頂點已經在螢幕座標繫上,不用再進行什麼世界變換、視圖變換、投影變換,也不用進行光線計算了。不過這時的原點就在客戶區的左上方了,其中x向右為正,y向下為正,而z的意義已經變為z-buffer的象素深度。那麼我們就在z=1.0f處畫這個矩形就行了,沒有比1.0f更遠的了!
有矩形了,那麼怎麼把環境貼圖映射到上面呢?用HLSL一句搞定!(GPU編程不是蓋的)。
不過別記了把紋理座標向量先算出來:
| Output.Tex = normalize( mul(Input.Pos, g_mInvWorldViewProjection) ); |
至於映射嘛,用texCUBE 就行了
文法
ret texCUBE(s, t) |
Name |
In/Out |
Template Type |
Component Type |
Size |
s |
in |
object |
samplerCUBE |
1 |
t |
in |
vector |
float |
3 |
ret |
out |
vector |
float |
4 |
|
|
|
|
|
|
代碼:
| float4 color = texCUBE( EnvironmentSampler, Input.Tex ); |
注意:texCUBE需要顯卡支援PixelShader1.1,如果用到偏導數則需要PixelShader2.0
查了一下我的顯卡(Intel整合的GMA900),剛好支援PS2.0,我心裡那個激動呀……激動的我都不知道該怎麼表達我的感情了
看看我做的效果吧:
References
The DirectX Software Development Kit