轉自:http://www.cnblogs.com/graphics/archive/2009/11/25/1583682.htmlhtml
DirectXDraw Surface file format, .dds。這是微軟從DirectX7開始引進的一種文件格式,它用來存儲壓縮的或未壓縮的紋理,該格式支持mimaps cube maps和volume maps, D3DX和許多其餘的DX工具都支持這種格式,好比DirectX Texture Editor(dxtex.exe)和Texture Conversion Tool(Texconv.exe),從D3D110開始,DDS文件也支持紋理數組編程
DirectX Graphics Infrastructure 數組
MeshConvert.exe,這個tool位於Microsoft DirectX SDK \Utilities\bin\x86目錄下面,能夠用來轉換.x文件,支持.x, .obj, .sdkmesh格式之間的相互轉換,.sdkmesh是微軟新的格式在DX10/DX11以後使用,用來取代.x格式,MeshConvert是一個命令行工具,使用方法以下緩存
Usage: meshconvert <options> <input filename>數據結構
<input filename> Input mesh filename. The input file can be of .x, .obj, or .sdkmesh format /o <file> Optional output mesh filename /y Overwrite existing destination file /n Generate normals /t Generate tangents /tb Generate tangents and binormals /tcount <count> Texcoord count for the output mesh /a Output animation information /op Vertex cache optimize the mesh before exportin (non-functional) /sdkmesh [default] convert to .sdkmesh binary file /x convert to .x binary file /xt convert to .x text file /v Verboseapp
.SDKMesh is a simple custom mesh format used by new SDK samples框架
使用DirectX Control Panel能夠方便的設置DirectX相關的東西,好比用Debug庫仍是Release庫,是否檢測內存泄漏,是否容許Shader調試等等,這個工具的位置在...\Microsoft DirectX SDK\Utilities\bin\x86,界面以下圖。編程語言
PIX是調試和分析D3D應用程序的,該工具位於...\Microsoft DirectX SDK\Utilities\bin\x86下,關於它的用法,DX幫助文檔中有詳細的說明,位於tools-DirectX Performance Tools-PIX下,工具截圖ide
有時候在釋放資源的時候會出現運行時錯誤,這多是因爲資源之間的依賴形成的,好比下面的代碼,運行時會出現一個違規訪問的錯誤,爲何呢,由於m_SoundBuffer是依賴m_pDirectSound的,而m_pDirectSound先釋放了,因此m_SoundBuffer變得不可訪問了
將兩者釋放的順序交換一下就行了,以下。
有不少圖形學書籍都講到過,先旋轉再平移和先平移再旋轉效果是不同的,同理,先縮放再平移和先平移再縮放也是不同的。
爲了渲染,通常的對象都有個Render函數,在渲染以前要作一些變換,好比移動旋轉之類的,可是切記不可在Render函數中作這些變換,由於Render函數是被實時調用的,若是在這裏作變換,則一個變換會被應用不少次。
Remember in Direct3D the vertices must be defined in clockwise order. see the picture below, the order is v0, v1, v2, v3
這個函數返回的是當前時間-單位毫秒,但是類型是DWORD,而咱們通常作計算都須要float類型,轉換一下,通常應該先計算差值,再作類型轉換
而不要這樣作:
這樣是要損失精度的,由於DWORD是32爲整數,而float只有24位精度,此法不可取。
一般咱們用下面的代碼來防止頭文件被重複包含,這是標準的寫法
還有一種方法是,這種方法是MS特有的,不適合其餘平臺,因此推薦使用第一種方法
有不少幾年前編寫的遊戲書籍,其中所附代碼大可能是基於VC6的,而咱們如今用的大可能是VS2005/VS2008/VS2010,因此須要一次轉換,而在轉換中常常會遇到編譯或者連接錯誤,解決辦法以下:
編譯錯誤:error C2440: '=' : cannot convert from 'char [14]' to 'LPCWSTR'
這是因爲做者默認使用的是函數的A版本,而咱們的工程使用了W版本。
解決辦法一:手動將全部函數改成A版本,例如MessageBox -> MessageBoxA, 不推薦這種防範。或者將全部字符串改成寬字符串,即在字符串前加大寫字母L,這個方法比較笨,可是確實好的方法。推薦使用。
解決辦法二:在工程文件上點右鍵-Properties-Configuration Properties-C/C++-Preprocessor-Preprocessor Definitions-點擊右邊的省略號按鈕-在彈出的對話框中將Inherit from parent or project defaults選項去掉便可。這個方法一勞永逸,能夠一次性去除全部此類編譯錯誤。可是卻不是好的編程習慣,咱們應該儘可能使用函數的W版本。
連接錯誤:unresolved external symbol xxx
這種錯誤通常都是因爲缺乏lib文件致使的,只要引用正確的lib文件就能夠了
解決辦法:在工程文件上點右鍵-Properties-Configuration Properties-Linker-Input-Additional Dependencies-點擊右邊的小省略號按鈕-將所需的lib文件加入到彈出的對話框中便可。
經過註冊表也能夠設置D3D的調試選項,這和使用DirectX控制面板是同樣的,並且二者是相通的,改變一個,另外一個也會跟着改變,以下,註冊表位置:
HKLM\Software\Microsoft\Direct3D
有不少時候須要用到視線,好比Billboard技術,要求被觀察物體始終面對觀察者,這時候就須要該物體與視線垂直,求取視線很簡單,用觀察點減去眼睛的位置便可
不少圖形軟件都支持該效果,在瀏覽一個model的時候,鼠標滾輪向前滾時(mouse wheel rotate forward, away from the user),model會逐漸變大,謂之zoom in,鼠標滾輪向後滾時(mouse wheel rotate backward, toward the user),model會逐漸變小,謂之zoom out
那麼這個效果是如何實現的呢?在我初學DirectX的時候,一直覺得用縮放變換來實現。直到研究了DXUT的Camera類之後,才發現,其實有一個更簡單的辦法。經過改變Camera與Model之間的距離來實現,這與現實生活中的感受是同樣的,當咱們離一個物體近的時候,感受它很大,而當咱們漸漸遠離它的時候,它會變得愈來愈小,此其因此然也!編程的樂趣就在於靈活!
Transform(變換)的本質就是從一個座標系到另外一個座標系的過程 world transform model space -> world space
view transform world space -> view/camera space
projection transform view/camera space -> projection space
transform engine(變換引擎) 以頂點爲輸入,對其進行world, view and projection transform, 而後進行剪
裁,將結果傳送給rasterizer進行光柵化
//world transform經過下面的代碼完成 // 將model移動至原點 D3DXMATRIXA16 matWorld ; D3DXMatrixTranslation( &matWorld, 0.0f, 0.0f, 0.0f) ; g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
//view transform經過下面的代碼完成 D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-10.0f ); //眼睛位置 D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); //觀察中心 D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); //向上向量 D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
projection transform經過下面的代碼完成 D3DXMATRIXA16 matProj; //視角:pi/4,即45度 //縱橫比:1:1 //近剪裁平面:1.0f //遠剪裁平面:1000.0f D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
在D3D中Point和vector都是用三維座標表示的,好比,給定 v = [x, y, z], 如何區分這是一個點仍是一個向量呢 答案是:在三維座標下沒法區分,因而在最後再加一維,造成齊次座標 v = [x, y, z, w], 實際應用中w一般取值1 規定以下: w = 1時,v表示點 w = 0時,v表示向量 爲何呢? 先看一下平移變換的矩陣
由於向量是沒有位置屬性的,向量只有長度和方向兩個屬性,即平移一個向量是沒有意義的 因此將向量的第四維w設置爲0,阻止平移。 可是點是有位置屬性的,平移一個點也是有意義的,因此將點的w置爲1,使之能夠平移
一般這種需求都是逆向的,由於正向的D3D已經作了 好比對於一個view space中的model,如何把它變換到world space呢?(在D3D頂點處理流水線中world space是view space的前一個過程) 首先咱們應該知道world space -> view space 是怎樣一個過程,瞭解了這個過程後,應用它的逆過程便可 顯然,world space -> view space是經過視圖變換實現的,這個變換矩陣就是view matrix,好了,如今咱們須要作的是: 1. 找出這個view矩陣 2. 求出它的逆矩陣 3. 將該逆矩陣應用到要變換的模型 下面以一個點爲例,假設咱們要將點p(x, y, z) 從view space變換到world space
步驟: 首先求出view matrix D3DXMATRIX view; Device->GetTransform(D3DTS_VIEW, &view);
再求出它的逆矩陣 D3DXMATRIX viewInverse; D3DXMatrixInverse(&viewInverse, 0, &view);
而後將這個矩陣乘到這個點上便可 D3DXVec3TransformCoord(p, p, viewInverse);
注:D3DXVec3TransformCoord是用來變換點的(即w=1的vector) 而 D3DXVec3TransformNormal是用來變換向量的(即w=0的vector)
若是須要對同一個圖形連續進行多個變換,那麼能夠把多個變換矩陣連乘造成一個矩陣。
但矩陣乘法不知足交換律,因此連乘的順序很重要。
大多數文檔都是以左右順序來區分的,這是不許確的,並且不便於理解和記憶。
這裏講一個規則,比較方便
規則:在連乘式中,離被變換頂點近的矩陣對應的變換先進行。
好比,對頂點P(x, y, z, 1)進行以下變換
1. 平移到(1, 1, 1)點,變換矩陣爲MT
2. 繞z軸旋轉30度,變換矩陣爲 MR
3. 放大2倍,變換矩陣爲 MS
那麼正確的連成順序是
P * MT * MR * MS (在DirectX文檔裏多采用這種寫法)
MT離P最近,那麼它是最早進行的變換,MR次之,MS再次。
不少書籍或文檔裏面說是按照從左到右的順序連乘,可是別忘了頂點在公式中的位置
若是頂點在右邊,那麼就變成了下面的形式
MS * MR * MT * PT (在以OpenGL爲基礎的圖形學書籍裏多采用這種寫法)
因此準確的說應該是,在連乘式中,先進行的變換離被變換的頂點近。
注意若是P在連乘式右邊,那麼應該取其轉置形式,不然沒法與矩陣相乘。
由於三維的矩陣沒法完成某些變換,好比平移變換對應的矩陣以下
這用三維矩陣是沒法實現的,相似的還有透視投影變換,因此在D3D中使用4×4矩陣來實現變換,又一個問題來了,因爲3D中的頂點都是三維的,三維的vector和四維的matrix是沒法相乘的,因而在三維的頂點後面再加上一維,造成齊次座標,以下
[x, y, z, w]
最後一維一般用w表示,而w一般取值1
這樣就能夠用一個1×4的vector與一個4×4matrix相乘了。
[x, y, z, w] *
這個頭文件包含了幾乎D3D用到的全部頭文件,若是編譯、連接或者運行有問題,能夠嘗試包含這個文件試試。
若是安裝了DirectX SDK,可使用其中的工具DirectX Caps Viewer 來查看,這個工具在DirectX的開始菜單中,也在SDK安裝目錄的Utilities\Bin\x86(x64)下面
打開這個工具後,依次展開結點DirectX Graphics Adapters-video card name-D3D Device Types-HAL-Caps
注意:必定要選擇HAL分支,這纔是你顯卡真正支持的特性,而Reference目錄下存儲的是全部D3D特性,這是用軟件模擬的,速度奇慢,只有在安裝了DirectX SDK的機器上纔可用,這就是HAL Device和Reference Device的區別,你們能夠查看SDK幫助文件中Device Type一節來獲取詳細的信息
若是沒有安裝DirectX SDK, 可使用Everest來查看
看這裏吧,比較詳細
設u和v是兩個三維向量,α是它們之間的夾角
點積
u·v = ux*vx + uy*vy + uz*vz =|u|*|v|*cos(α)
乍一看,幾何意義不十分明顯,注意:當u和v都是單位向量時,點積就是兩個向量夾角的餘弦值
D3D中常常用這種方法來求夾角或者旋轉角度,或者頂點法向量與入射光的夾角。
叉積
u×v = [(uyvz - uzvy), (uzvx - uxvz), (uxvy - uyvx)] =|u|*|v|*sin(α)
叉積的結果同時垂直於兩個向量
叉積的結果值是以u和v爲鄰邊的平行四邊形的面積,叉積能夠用來求多邊形的面積
global variables are implicitly constant, enable compatibility mode to allow modification
編譯Shader程序時遇到如下錯誤
全局變量默認是常量,貌似在Shader程序中不能修改?新版的HLSL編譯器不支持
解決辦法:
將D3DXCompileShaderFromFile的第六個參數改成D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY便可
若是程序執行後,窗口出現花屏現象,那麼多半是因爲depth buffer沒有clear致使的,好比下面這幅圖就是一個花屏的例子。
解決辦法,在調用Clear函數時,將depth buffer也clear一下便可。原來多是這樣調用的
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 1.0, 0 ); //僅僅clear render target
修改後以下
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , 0xff00ff00, 1.0, 0 );
須要注意的是,這個Clear函數可能會失敗,好比你在CreateDevice的時候並無建立depth buffer,而在Clear函數中卻要Clear depth buffer,因此請檢查你的CreateDevice函數,確保設備確實有一個關聯的depth buffer。
轉自:http://blog.csdn.net/fuli1215/article/details/5961632
DirectX 9.0
1:平面(法向量(normal vector)和平面中一點表示。
2,D3DX庫用以下結構體來表示一個平面類,typedef struct D3DXPLANE{}
3點和平面的空間關係
Direct3D 基礎
一:
1, 初始化Direct3D
2, Direct3d 能夠被視做應用程序與圖形設備(3d硬件)的交互中介
3, 一箇中間環節 HAL(hardware abstraction layer)硬件抽象層,HAL是一個指示設備完成某些操做的設備的相關代碼集。規範 specification
4, 軟件定點運算???
二:
REF設備:Direct3D提供了參考光柵設備(reference rasterizer device),它能以軟件的方式徹底支持direct3d API。
注意:REF設備僅用於開發階段,它與direct SDK捆綁(ship)在一塊兒,沒法發佈給最終的用戶,此外REF設備的速度十分的緩慢,在測試之外的其餘場合都很不實用。
D3DDEVTYPE :HAL 設備用值D3DDEVTYPE_HAL來指定,
1.2 COM(組建對象模型)
COM(Component Object Model)是一項能使Direct 獨立於編程語言並具有向下兼容的技術,可將其視爲一個C++類來使用
建立COM接口時不可以使用C++關鍵字new ,用完後應該用 Release方法而不是delete,
注意:COM接口都有一個前綴I,
1.3 預備知識
1.3.1 表面
表面主要是Direct3d 用於存儲2D圖像數據的一個像素矩陣。
線性數組(linear array)
跨度(pitch,stride的同義語)用字節表示,
代碼中用 接口 IDirect3DSurface9來描述表面。
獲取(retrieve)
1.3.2 多重採樣
用像素矩陣表示圖像時每每出現塊狀(blocky-looking)效應,多重採樣(multisampling)時一項用於平滑塊狀圖像的技術。
全屏反走樣(full-screen antialiasing)
多重採樣會下降應用程序的運行速度。若是要使用多重採樣技術 ,請務必使用IDirect3D9::CheckDeviceMultiSmpleType 方法來檢查你的設備是否支持多重採樣。
1.3.3 像素格式
1.3.4 內存池(memory Pool)
內存池能夠用D3DPOOL 枚舉類型來表示,、
顯存(video memory)
1.3.5 交換鏈和頁面置換
表面集合(collection),交換鏈(Swap Chain),該集合用接口Idirect3DswapChain9 來表示,
置換技術(page Flipping),這兩項技術主要用於生成更加平滑的動畫。
前臺緩存槽(front buffer slot),幀頻(frame rate),後臺緩存(back buffer)
1.3.6 深度緩存
深度緩存(depth buffer)是一個只含有特定像素的深度信息而不含圖像數據的表面。
深度項(entry)。
Z-緩存 (z-buffering)。//前面的物體遮擋後面的物體。
深度緩存的格式決定了深度測試的精度。
1.3.7 定點運算
定點運算(vertex processing) 分爲兩種,即:軟件定點運算(software vertex process)或硬件定點運算(hardware vertex proceeding)。不管怎樣 ,軟件定點運算老是被支持,因此老是能夠實現的。但咱們應該始終優先考慮硬件定點運算的方式,由於速度更快,並且能夠不佔用cpu資源,也就意味着cpu能夠被解放出來進行其餘的運算。
注意:圖像卡支持硬件定點運算的另一種等價的說法是該圖形卡支持變換和光照的硬件計算。
1.3.8 設備性能
bool supporthardware ;
if(caps.DevCaps &D3DDEVCAPS_HWTRANSFORMNDLIGHT)
{
Supporthardware=true;
}
Else
{
Supporthardware=FALSE;
}
注:DevCaps 表示「設備性能 (Device Capabilities)」
1.4 Direct3D 的初始化
初始化的過程能夠分爲以下的步驟:
1:獲取接口IDirect3d 的指針。獲取物理硬件信息並建立接口IDirect3Ddevice9該接口爲一個C++對象。
2:檢查設備性能(D3DCAPS9),判斷主顯卡(primary display adapter)是否支持硬件定點運算。
3:初始化D3DPRESENT_PARAMETERS結構中的一個實例。
4:利用已經初始化的D3DPRESENT_PARAMETERS結構建立IDirect3Ddevice對象。
1.4.1 獲取接口IDirect3D9的指針
IDirect3D9 * _d3d9;
_d3d9=Direct3DCreate9(D3D_SDK_VERSION);
_d3d9對象的用途:設備枚舉(device enumeration)以及建立IDirect3DDevice9類型的對象。
1.4.2 校驗硬件頂點運算
1.4.3填充D3DPRESENT_PARAMETER結構
1.4.4建立IDirect3DDevice接口
HRESULT IDirect3D9::createDevice();
1.5 例程,Direct3D的初始化
InitD3D 函數對應用程序主窗口進行初始化,若是成功,則返回一個已經建立好的IDirect3DDevice接口指針。(這個函數咱們能夠指定窗口的尺寸,運行模式)。
EnterMsgLoop 該函數封裝了應用程序的消息循環。
1.5.2 例程框架
。。。。bool Setup()例程所需進行的所有設置和初始化都在改函數中進行。如分配資源,檢查設備性能,設置應用程序的狀態。
。。。。。void Cleanup()該函數用於釋放在setUP函數中分配的任何資源。
。。。。。bool Display(float timedelta).實現所有的繪製代碼以及相鄰幀之間應該執行的操做。
1.5.3 例程 D3D初始化
第二章 繪製流水線
繪製流水線(rendering pipeline)
場景(scene)是物體和模型的集合。
任何物體均可以用三角形網格(triangle mesh)逼近表示。三角形網格是構建物體模型的基本單位。多邊形(polygons),圖元(primitives),網格幾何元(mesh geometry),
定點格式:
定點除了包含空間信息外,還包含其餘的附加屬性,如顏色屬性,法線(normal)屬性,
靈活定點格式(flexible vertex format fvf),
2.1.2
三角形單元
三角形個定點的指定順序很是重要,咱們稱爲繞序(winding order),
2.1.3 索引
索引(indices),其原理,咱們建立一個定點列表和一個索引列表,定點列表包含了所有獨立定點,索引列表包含了指向定點列表的索引,這些三角形規定了爲構建三角形單元,各定點應按何種方式來組織,
定點列表能夠這樣來建:
Vertex vertexlist【4】={v0,v1,v2,v3}
接下來,藉助索引列表來定義頂點列表中頂點的組織方式以構成兩個三角形單元。
WORD indexList【6】={0,1,2,0,2,3}
2.2 虛擬攝像機
可見的空間體積(volume of space)。視域體(frustum)
丟棄看不見的視域體的這類數據運算過程咱們稱爲裁剪(clipping)。
投影窗口(projection window)是一個2D區域,
2.3 繪製流水線
一個簡單的繪製流水線
局部座標系-》世界座標系-》觀察座標系-》背面消隱-》光照-》裁剪-》投影-》視口座標系-》光柵化。
局部座標系到世界座標系的變換:
Device-》SetTransform(D3DTS_WORLD,&worldMatrix);
2.3.1 局部座標系
局部座標系(local space)又叫建模座標系(modeling space),是用於定義構成物體三角形單元列表的座標系,
2.3.2世界座標系
世界座標系又叫全局座標系,一個位於局部座標系的物體經過一個叫世界變換(world transform)的運算(過程)變換的世界座標系(world space),該變換一般包括平移(translation),旋轉(rotation)以及比例(scaling)運算,
世界變換用一個矩陣來表示,並由Direct3D經過IDirect3DDevice9::SetTransform方法來加以應用,該方法的第一個參數表示要變換的類型,如 要進行世界變換則要設爲:D3DTS_WOLRD,第二個參數表示採用的世界變換矩陣。
2.3.3 觀察座標系
在世界空間中,集合體和攝像機都是相對世界座標系定義的,
取景變換(view space transformation),咱們稱變換後的集合體位於觀察座標系(view space)中,
取景變換矩陣(即觀察矩陣)可由以下D3DX函數計算獲得:
D3DXMATRIX *D3DXMaTrixLookAtlLH();
例如攝像機位於(5,3,-10),其觀察點位世界座標系的原點(0,0,0),咱們就能夠這樣建立取景變換矩陣:
D3DXVECTOR3 position(5.0f,3.0f,-10.0f);
D3DXVECTOR3 targetPoint(0.0f,0.0f,0.0f);
D3DXVECTOR3 worldUp(0.0f,1.0f,0.0f);
D3DXMATRIX V;
D3DXMatrixLookAtLH(&v,&targetPoint,&worldUp);
Device->SetTransform(D3DTS_VIEW,&v);
2.3.4背面消隱
每一個多邊形都有兩個側面(sides),咱們把其中的一個側面標記爲正面(front side),另外一個側面標記爲背面(back side),一般,多邊形的背面是看不見的,由於場景中的多數物體都是封閉的(enclosed volume),背面消隱(backface culling)。
Direct3D認爲頂點排列順序爲順時針(觀察座標系中)的三角形單元是正面朝向的,頂點排列順序爲逆時針(觀察座標系)的三角形單元是背面朝向的。
若是由於某種緣由,默認的消隱方式不能知足用戶的要求,咱們能夠經過修改繪製狀態(render state)D3DRS_CULLMODE來達到目的。
Device->SetRenderState(D3DRS_CULLMODE,Value);
其中,value的值能夠取:
D3DCULL_NONE 徹底禁止背面消隱
D3DCULL_CW 只對順時針繞序的三角形單元進行消隱
D3DCULL_CCW 默認值,只對逆時針繞序的三角形單元進行消隱
2.3.5 光照
光源是在世界座標系中定義的,但必須通過取景變換到觀察座標系中才可使用。
固定的流水線(fixed function pipeline)。
2.3.6裁剪
一個三角形單元與視域體的相對位置關係有如下三種:
。。徹底在內部
。。徹底在外部 將被踢出
。。部分在內(外),
2.3.7 投影
觀察座標系中,咱們的任務是獲取3D場景的2D表示,從N維變換到N-1維的過程稱爲投影(projection),
咱們只關心透視投影(perspective projection),它能夠產生「透視縮短(foreshortening)」的視覺效果,即近大遠小,
投影變換定義了視域體,並負責視域體中的幾何體投影到投影窗口,投影矩陣比較複雜,咱們將使用D3DX函數,其功能是依據視域體的描述信息建立一個投影矩陣。
D3DXMATRIX *D3DMatriPerspectiveFovLH(D3DXMATRI &pout,
FLOAT fovy,FLOAT Aspect,FLOAT zn,FLOAT zf);
橫縱比(aspect ratio)參數,投影窗口中的幾何體最終將變換到屏幕顯示區,從方形的投影窗口到矩陣的顯示屏的變換會致使拉伸畸形(stretching distortion),所謂縱橫比就是顯示屏縱橫兩維尺寸的比率,經常使用於矯正由方形到矩形的映射而引起的畸形。
縱橫比(aspect ratio)=屏幕寬度(screen width)/屏幕高度(screen height)。
Zn 近裁剪面到座標原點的距離
Zf 遠裁剪面到原點的距離
2.3.8 視口變換
視口變換(viewport transform)的任務就是將頂點座標從投影窗口轉換到屏幕的一個矩形區域中,該矩形區域成爲視口(viewpoint)。
在Direct3D中,視口用結構D3DVIEWPORT9來表示。
Typedef strut D3DVIEWPORT9{
DWORD X,
DWORD Y,
DWORD width,
DWORD height,//前四個變量定義了矩形相對於父窗口的位置和大小
DWORD MINZ,//指定了深度緩存中的最小深度值。
DWORD MAXZ//深度緩存中最大深度值
}D3DVIEWPOER9;
注意,MINZ MAXZ的範圍設定在【0,1】,除非你想最求某中特效,不然其值都應該限制在這個範圍。
實例:
D3DVIEWPORT9 vp={0,0,640,480,0,1};
Device->SetViewport(&vp);
2.3.9 光柵化
光柵化(rasterization)的任務就是爲了繪製每一個三角形單元,如何計算構成三角形單元的每一個像素的顏色值。光柵化的計算量很是大,咱們通常要藉助專門的圖形卡的加速功能,光柵化的最終結構就是顯示在屏幕上的一幅2D圖像。
小結
在觀察座標系中,攝像機位於座標原點,光軸方向與z軸正向一致,物體變換到觀察座標系後,就能夠經過投影映射到投影窗口中,視口變換將投影窗口中的幾何體在映射到視口中,最終在繪製流水線的光柵階段計算出最終顯示的2D圖像的每一個像素的顏色值。
第三章 Direct3D中的繪製
3.1 頂點緩存與索引緩存
頂點緩存和索引緩存(vertex/index buffer)是兩類類似的接口。
爲何不用數組呢?由於頂點緩存和索引緩存能夠被放置在顯存(video memory)中,進行繪製時,使用顯存中的數據將得到比使用系統內存中的數據開得多的繪製速度。
在代碼中 ,頂點緩存用接口IDirect3DVertexBuffer9 表示,索引緩存用接口IDirect3DIndexBuffer9表示。
3.1.1
建立頂點緩存和索引緩存
HRESULT IDirect3DDevice9::CreateVertexBuffer(
UINT Length,//爲緩存分配的字節數 若是有8個定點,則爲 8*sizeof(Vertex)
DWORD Usage,////緩存的一些附加屬性
DWORD FVF,//存儲在定點緩存中頂點的靈活頂點格式
D3DPOOL POOL,//容納緩存的內存池
IDirect3DVretexBuffer9 **ppvertexBuffer,//用於接收所建立的頂點緩存的指針
HANDLE *Psharehandle);//不使用,該值設爲0
HRESULT IDirect3DDevice9 ::CreateIndexBuffer(
UINT Length,
DWORD Usage,
D3DFORMAT Format,//指定索引的大小,設爲D3DFMT_INDEX16表示16位索引,
IDirect3DIndexBuffer9 **ppIndexBuffer,//用於接收所建立的索引緩存指針
HANDLE psharedhandle);
注意:
建立緩存時,若是未使用D3DUSAGE_DYNAMIC,則所建立的緩存爲靜態緩存(static Buffer),咱們用靜態緩存來存儲靜態數據(那些不須要常常修改或訪問的數據),例如,地圖和城市建築的數據,若是使用的動態緩存,動態緩存通常放置在AGP存儲區中,其內容能夠迅速的更新,動態緩存的一個最大的優勢是更新的速度很是的快,它的一個很常見的例子就是粒子系統,
3.1.2
訪問緩存內容
能夠藉助方法Lock來獲取指向緩存內容的指針,但訪問完以後,必須對緩存進行解鎖(unlock),
HRESULT IDirect3DVertexBuffer9::Lock(
UINT offsetToLock,從哪裏開始鎖定
UINT SizeToLock,//要鎖定的長度(字節數)
BYTE **ppbdata,//指向被鎖定的存儲區位置的指針
DWORD flags//鎖定的方式,
};
3.1.3 獲取頂點緩存和索引緩存的信息
D3DVERTEXBUFFER_DESC vbDescription;
vertexBuffer->GetDesc(&vbDescription);
3.2 繪製狀態
Direct3D封裝了多種繪製狀態(rendering state),這些繪製狀態將影響幾何體的繪製方式。
HRESULT IDirect3DDevice9::SetRenderState(
D3DRENDERSTATETYPE State,
DWORD Value);
3.3 繪製的準備工做
在繪製以前,咱們還有三個步驟須要完成:
(1):指定數據流輸入源。將頂點緩存和數據流進行鏈接。方法
HRESULT IDirect3DDevice9::SetStreamSource(
UINT,//標識與頂點緩存創建鏈接的數據流,咱們總設爲0
IDirect3DVertexBuffer9,//指向與給定數據流創建鏈接的頂點緩存的指針
UINT,//自數據流的起點的一個偏移量。單位爲字節,
UIN);//將要鏈接到數據流的頂點緩存中每一個元素的大小,單位爲字節
例如:
_device->SetStreamSource(0,vb,0,sizeof(Vertex));
(2),這隻頂點格式
_device->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);
(3),設置索引緩存
_device->SetIndices(_ib);
3.4 使用頂點緩存和索引緩存進行繪製
即便用DrawPrimitive 或DrawIndexedPrimitive方法將待繪製幾何體的信息經過繪製流水線傳輸,這兩個方法從頂點數據流中獲取頂點信息,並從當前設定的索引緩存中提取索引信息。
3.5 D3DX幾何體
D3DX庫提供了以下6個網格建立函數:
。D3DXCreateBox
D3DXCreateSphere
D3DXCreateCylinder
D3DXCreateTeapot
D3DXCreatePolygon
D3DXCreateTorus
上述六個方法都很是的類似,都使用D3DX網格數據結構ID3DXMesh和ID3DXBuffer接口,
3.6 例程,三角形,立方體,茶壺,D3DXCreate*
第四章 顏色
這一章咱們學習如何爲幾何體添加顏色
4.1 顏色的表示
1.在Direct3D中,顏色用RGB三元組來表示,三種顏色的加性混合(additive mixing)決定了最終的顏色。
2.RGB數據可用兩種不一樣的格式來保存,第一種是D3DCOLOR,它實際上與DWORD類型徹底相同,共有32位,Direct3D提供了D3DCOLOR_ARGB宏幫助咱們完成這項工做,如:
D3DCOLOR brightRed=D3DCOLOR_ARGB(255,255,0,0);
D3DCOLOR_XRGB能夠代替D3DCOLOR_ARGB;
在Direct3D中,存儲顏色數據的另一種結構是D3DCOLORVALUE,咱們用單精度浮點數來度量每一個顏色的亮度值,範圍爲0-1,
咱們也能夠用D3DXCOLOR替代D3DCOLORVALUE,且兩種都有4個浮點類型的成員,這樣咱們就能夠將其表達成一個4D向量,故其運算與向量徹底同樣,在D3DXCOLOR中顏色的乘法表示成各份量的值分別相乘。
4.2 頂點顏色
圖元的顏色有構成該圖元的頂點顏色決定。
Struct colorVertex{
Float x,y,z;
D3DCOLOR color;
Static const DWORD FVF;
}
Const DWORD ColorVertex::FVF=D3DFVF_XYZ|D3DFVF_DIFFUSE;
4.3着色(shading)
目前咱們使用兩種着色模式(shading mode),平面着色(flat shading)和Gouraud着色(gourand shading)。
若是使用平面着色模式,則每一個圖元的每一個像素被一致的賦予該圖元的第一個頂點所指定的顏色。平面着色容易使物體呈現塊狀,這是由於各顏色沒有平滑的過渡,平滑着色(smooth shading),其中各圖元的顏色由個頂點的顏色線性插值獲得,
着色模式由Direct3D狀態機(state maching)控制,
Device->SetRenderState(D3DRS_SHARDMODE,D3DSHADE_FLAT或者D3DSHADE_GOURAUD);
4.4 具備顏色的三角形
第五章 光照
光照(lighting)有助於描述實體形狀和立體感。使用光照咱們無需自行指定頂點的顏色值,Direct3D會將頂點送入光照計算引擎(light engine),依據光源類型,材質(material)以及物體表面相對於光源的朝向,計算出每一個頂點的顏色值,基於某中光照模型計算出的個頂點的顏色,繪製結果更加的逼真。
5.1 光照的組成
在Direct3D的光照模型中,光源發出的光由如下三個份量或三種類型的光組成。
。環境光(Ambient light),反射
。漫射光(Diffuse light),這種類型光沿着特定的方向傳播。當它到達某一表面時,將沿着各個方向均勻反射。漫射光方程(diffuse lighting equation).
.鏡面光(specular light),這種類型的光沿着特定方向傳播,光到達某一表面時,將嚴格的按照另外一個方向反射。由於鏡面光的計算量很是大,因此Direct3D爲其提供了開關選項,通常都是關了的,若是要開啓,必須:
Device->SetRenderState(D3DRS_SPECULARENALE,true);
每種類型的光均可以用結構D3DCOLORVALUE 或D3DXCOLOR來表示。這些類型描述了光線的顏色,
5.2 材質
材質容許咱們定義物體表面對個顏色光的反射比例。材質結構用D3DMATERIAL9來表示。
Typedef struct D3DMATERIAL9{
D3DCOLORVALUE ;//材質對漫射光的反射率
D3DCOLORVALUE;//材質對環境光的反射率
D3DCOLORVALUE;鏡面光的反射率
D3DCOLORVALUE;加強物體的亮度
Float ;鏡面高光點的銳度(sharpness),該值越大,高光點的銳角越大
}D3DMATERIAL9,*LPD3DMATERIAL9;
具體使用例子見書
5.3 頂點法線 是一個描述多邊形朝向的向量。
頂點法線(Vertex normal)正是基於上述思路而產生的,
光照計算是對每一個頂點進行的,因此Direct3D須要知道表面再每一個頂點處的局部朝向(法線方向),注意頂點法線和表面法線不必定相同,例如近似的求和園。
Struct Vertex{
Float x,y,z;
Float _nx,_ny,_nz;
Static const DWORD FVF;
};
Const DWORD Vertex::FVF=D3DFVF_XYZ|D3DFVF_NORMAL;
注意咱們去掉了表示顏色的成員變量,這是由於咱們將用光照計算頂點的顏色。
一種更好的計算頂點法向量的方法是計算法向量均值(normal averaging),
注意:在變換的過程當中,頂點的法向量可能已經再也不規範化,因此,要規範化
Device->SetRenderState(D3DRS_NORMALIZENORMALS,TRUE);
5.4 光源
Direct3D支持三種光源
。點光源(point light),在世界座標系中有固定的位置
。方向光(directional lights),該光源沒有位置信息,
。聚光燈(spot lights),這種類型的光源與手電筒相似。有位置信息,光線呈錐形(conical shape)。有兩個角度,
在程序代碼中,光源用結構D3DLIGHT9來表示。
5.5 例程 光照
爲一個場景添加光照的步驟以下:
(1):啓用光照
(2):爲每一個物體建立一種材質,並在繪製相應物體前啓用(設置)該材質,
(3):建立一種或多種光源,設置並啓用
(4):啓用所用其他的光照狀態,如鏡面高光(specular highlightings)。
第六章 紋理映射(texture mapping)
藉此此技術 ,咱們能夠將圖像數據映射到三角形單元中,增長立體感,真實感。
在Direct3D中,紋理用接口IDirect3DTexture9表示,紋理相似於一個表面的像素矩陣,
6.1 紋理座標
紋理元:
爲了處理不一樣尺度的紋理,Direct3D將紋理座標作了規範化處理,使之限定在區間【0,1】中。
爲了實現該映射,必須修改頂點座標。
增長:float _u,_v;
6.2 建立並啓用紋理
HRESULT D3DXCreateTextureFromFile();
建立紋理
IDirect3DTextrue9 *_stone;
D3DXCreateTextureFromFile(_device,」stone.bmp」,&_stone);
設置當前紋理
Device->SetTexture(0,_stone);
禁用某一層紋理
Device->SetTexture(0,0);
renderObjectWithoutTexture();
6.3紋理過濾器
紋理過濾技術主要處理紋理三角形與屏幕三角形的大小不同的問題。
Direct3D提供了3種類型的紋理過濾器(fileter)。紋理過濾方式能夠用方法;
Device3DDevice->SetSamplerState來設置。
最近點採樣(nearest point samping)。
線性紋理過濾(linear filtering)
各向異性紋理過濾(anisotropic filtering),但使用此紋理時,必須對D3DSAMP_MAXAISOTROPIC 水平值進行設定,改值越大,圖像效果就越好。請調用IDirect3DDevice9::GetDeviceCaps函數檢驗返回D3DCAPS9結構參數。
Device->SetSamplerstate(0,D3DSAMP_MAXANISOTROPIC,4);
6.4 多級漸進紋理
多級漸進紋理鏈(Chain of mipmap),方法是,有某一紋理建立一系列分辨率逐漸減少的紋理圖像,而且對每種分辨率下的紋理所採用的過濾方式進行定製,以保證保留那些較重要的細節。
6.4.1 多級漸進紋理過濾器
使用Device->SetSamplerState(0,D3DSAMP_MIPFILTER,filter);
Filter能夠取不一樣的值,如:D3DTEXT_NONE,D3DTEXT_POINT,D3DTEXT_LINEAR.
6.4.2 使用多級漸進紋理
6.5 尋址模式
前面說過紋理座標必須限制在【0,1】中,但這樣是有問題的,Direct3D中定義了4中用來處理紋理座標值超出【0,1】區間的紋理映射模式,它們分別是:
重複(wrap)尋址模式(address mode),邊界顏色(border color )尋址模式,箝位(clamp)尋址模式,以及鏡像(mirror)尋址模式。
6.6 例程 紋理四邊形
如今來總結一下爲場景添加紋理映射的步驟:
(1):構造組成物體的頂點,併爲其指定紋理座標
(2):用函數D3DXCreateTextureFromFile爲IDirect3DTexture9接口加載一種紋理
(3):設置縮小過濾器,放大過濾器和多級漸進紋理過濾器
(4):繪製物體前,用函數IDirect3DDevice9::SetTexture來設定與該物體關聯的紋理。
第七章 融合技術
融合(blending)技術,能夠獲得透明效果
7.1 融合方程
融合:將當前計算獲得的像素(源像素)顏色值與先前計算獲得的像素(目標)顏色值進行合成的作法稱爲融合。
注意:融合的效果並不侷限於普通的玻璃類型的透明效果,
在融合運算時,必須遵循如下的原則:
首先繪製的那些物體不須要進行融合的物體,而後將須要進行融合的物體按照相對於攝像機的深度值進行排序,若是物體已處於觀察座標系中,該運算的效率會至關高,由於此時只需對z份量進行排序,最後,按照自後往前的順序逐個繪製將要融合運算的物體。
源融合因子,目標融合因子,Direct3D中,默認狀態下是禁止融合運算的,能夠開啓:
Device->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
注意:融合的計算量並不小,當你繪製完須要進行融合的幾何體以後,應該禁止Alpha融合,在對三角形單元組進行融合的時候,最好進行批處理,以後應當即繪製出來,這樣能夠避免在每幀圖像中都啓用和禁止融合運算。
7.2 融合因子
能夠經過繪製狀態D3DRS_SRCBLEND,D3DRS_DESTBLEND的值來對源融合因子和目標融合因子分別進行設定。
例如:
Device->SetRenderSate(D3DRS_SRCBLEND,Source);
Device->SetRenderState(D3DRS_DESTBLEND,Destination);
7.3 透明度
頂點顏色中的Alpha份量和材質。
Alpha份量主要用來指定像素的透明度(transparency)。
源融合因子和目標融合因子分別設置爲D3DBLEND_SRCALPHA,D3DBLEND_INVSRCALPA.
7.3.1Alpha 通道
咱們每每是從紋理的Alpha通道(channel)中獲取Alpha信息。Alpha通道是保留給存儲了Alpha份量的紋理元的一個額外的位集合(bits set)。
7.3.2 指定Alpha來源
若是當前的紋理擁有一個Alpha通道,Alpha值就取自該Alpha通道,若是沒有Alpha通道,Alpha值就取自頂點的顏色。
7.4 用DirectX Textrue Tool建立Alpha通道
DDS文件之專門的一種爲DirectX應用程序的紋理設計的圖像格式。可以使用D3DXCreateTextrueFromFile函數將DDS文件加載到紋理中,
7.5 例程 透明效果
融合處理的步驟總結以下:
(1):設置融合因子D3DRS_SRCBLEND ,D3DRS_DESTBLEND.
(2):若是使用Alpha份量,還需指定其來源
(3):啓用Alpha融合繪製狀態
第八章 模板
模板緩存(stencil Buffer)。模板緩存是一個用於得到某種特效(special effect)的離屏(off-screen)緩存,模板緩存的分辨率(resolution)與後臺緩存(back Buffer)和深度緩存(depth Buffer)的分辨率徹底相同,因此模板緩存與後臺緩存和深度緩存中的像素是一一對應的,它容許咱們動態的,有針對性的決定是否將某個像素寫入後臺緩存中。
8.1 模板緩存的使用
1.詢問硬件是否支持,再啓用 Device->SetRenderState(D3DRS_STENCILENABLE,TRUE/FALSE);
Device->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,0Xff000000,1.0f,0);
D3DCLEAR_STENCIL代表咱們要對模板緩存,目標緩存,深度緩存進行清空操做,第六個值爲指定要將模板緩存清爲什麼值。
8.1.1 模板緩存格式的查詢
8.1.2 模板測試
咱們可使用模板緩存對後臺緩存中的某些特定的區域進行繪製,斷定是否將某個像素寫入後臺緩存的決策過程稱爲模板測試(stencil test),其表達式爲:
(ref &mask)ComparisonOperation(value & mask)。
注:模板參考值(ref),模板掩碼(mask)按位運算獲得左操做數
返回值爲bool型。
8.1.3 模板測試的控制
1.模板參考值
模板參考值(stencil reference value)ref的默認值爲0,但可這樣將其改成1
Device->SetRenderState(D3DRS_STENCILREF,0X1);
注意:使用的爲16進制數
2.模板掩碼(mask)
模板掩碼用於屏蔽或隱藏ref和value變量中的某些值,例如:
Device->SetRenderState(D3DRS_STENCILMASK,0X0000ffff);
模板值。
咱們不能顯式的單獨設置模板的值,可是能夠對模板緩存進行清空操做。
下面咱們介紹與模板相關的繪製狀態:
比較運算:
咱們能夠經過繪製狀態D3DRS_STENCILFUNC來設置比較運算(comparison operation),該比較運算函數可取自以下枚舉類型:
Typedef enum D3DCAMPFUNC{
}
8.1.4 模板緩存的更新:
咱們能夠基於如下3種可能的情形定義模板緩存中的值如何進行更新:
一:第i行,第j列的像素模板測試失敗,咱們能夠藉助繪製狀態D3DRS_STENCILFAIL將模板緩存中處於一樣位置的項更新爲以下:
Device->SetRenderState(D3DRS_STENCILFAIL,StencilOperation);
二:第i行,第j列的像素深度測試失敗,這樣設置:
Device->SetRenderState(D3DRS_STENCILZFAIL,StencilOperation);
三:第i行,第j列的像素深度測試和模板測試均成功,咱們這樣設置:
Device->SetRenderState(D3DRS_STENCILPASS,StencilOperation);
StencilOperation的值可取如下的常量:
8.1.5 模板寫掩碼
寫掩碼(write mask),該值能夠屏蔽咱們將寫入模板緩存的任何值的某些位:
可用繪製狀態D3DRS_STENCILWRITEMASK來設定寫掩碼的值,默認爲0xffffffff。
下例咱們將對高16位進行屏蔽:
Device->SetRenderState(D3DRS_STENCILWRITEMASK,0X0000ffff);
8.2 例程 鏡面效果
8.2.1 成像中的數學問題:
D3DX庫給咱們提供了建立相對於任意平面的鏡像變換矩陣:D3DXMATRIX *D3DXMatrixReflect(D3DXMATRIX *pout;CONST D3DXPLANE *pPlane;);