深入Managed DirectX9(二)
生活随笔
收集整理的這篇文章主要介紹了
深入Managed DirectX9(二)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
???? 三維化三角形
再來(lái)看看我們的程序,看起來(lái)并不是那么“三維”。而且我們所做的都能用GDI+輕易完成。So,我們應(yīng)該怎樣在3維空間里繪圖,并且給人留下深刻的印象呢?實(shí)際上,簡(jiǎn)單的修改就能達(dá)到這樣的效果。
如果你還記得,先前在我們創(chuàng)建第一個(gè)三角形的時(shí)候,我們使用了一個(gè)叫做“經(jīng)過(guò)變換的”(transformed)坐標(biāo)系統(tǒng)。這種坐標(biāo)是顯示器的屏幕區(qū)所使用的坐標(biāo),也是最容易定義的。如果我們使用未變換過(guò)的坐標(biāo)系統(tǒng)會(huì)怎樣呢?實(shí)際上,未變換過(guò)的坐標(biāo)系統(tǒng)被廣泛的用于現(xiàn)代游戲場(chǎng)景。
與屏幕坐標(biāo)(screem space)相比我們定義這些坐標(biāo)時(shí),還應(yīng)在世界坐標(biāo)(world space)里定義每一個(gè)頂點(diǎn)。你可以把世界坐標(biāo)設(shè)想為一個(gè)無(wú)限大的三維笛卡兒坐標(biāo)。你可以把你的對(duì)象放到這個(gè)“世界”的任意位置。現(xiàn)在來(lái)修改我們的程序,繪制一個(gè)未經(jīng)過(guò)世界坐標(biāo)變換的三角形。
首先使用未變換頂點(diǎn)格式類型中的一種來(lái)改變?nèi)切蔚臄?shù)據(jù)。在這里我們只關(guān)心頂點(diǎn)的位置,以及顏色,因此使用CustomVertex.PositionColored。
CustomVertex.positionColored[] verts = new CustomVertex. positionColored[3];
Verts[0].SetPosition(new Vector3(0.0f,1.0f,1.0f));
Verts[0].Color = System.Drawing.Color.Aqua.ToArgb();
Verts[1]`````````
Verts[2]`````````
(參見DirectX sdk Tutorial 3: Using Matrices)
同樣改變VertexFormat屬性:
device.VertexFormat = CustomVertex.PositionColored.Format;
好了,現(xiàn)在運(yùn)行程序:什么也沒有發(fā)生,僅獲得一個(gè)填充過(guò)的窗口。在討論為什么之前,先來(lái)看看我們都作了些什么。就像你看到的,我們選擇了PositonColored結(jié)構(gòu)來(lái)保存數(shù)據(jù)。這個(gè)結(jié)構(gòu)用世界坐標(biāo)保存了頂點(diǎn)的位置,也保存了它的顏色。因?yàn)闉轫旤c(diǎn)是沒有變換過(guò)的,所以我們使用Vector3類來(lái)代替Vector4類,沒有變換過(guò)的頂點(diǎn)是沒有rhw值的。Vector3結(jié)構(gòu)的成員直接映射為世界坐標(biāo)系里x,y,z的值。同時(shí),我們需要確定DirectX3D知道所做的改變,所以我們通過(guò)更新VertexFormat屬性來(lái)讓固定功能管道使用新的未變換但填充過(guò)顏色的頂點(diǎn)。
So,為什么程序運(yùn)行時(shí)沒有正確的顯示呢?問(wèn)題在于,我們只是在世界坐標(biāo)里繪圖,但并沒有給DirectX3D任何關(guān)于如何來(lái)顯示它們的信息。我們需要為場(chǎng)景添加一個(gè)攝像機(jī)來(lái)確定如何觀看我們的頂點(diǎn)。在經(jīng)過(guò)變換的坐標(biāo)系統(tǒng)里不需要攝像機(jī)的原因是:DirectX3D已經(jīng)知道在屏幕的哪個(gè)位置來(lái)顯示頂點(diǎn)。
在device上通過(guò)兩個(gè)不同的變換來(lái)控制攝像機(jī)。每一種變換都被定義為一個(gè)4×4的矩陣傳遞給DirectX3D。(???each transform is defined as a 4*4 matrix that you can pass in to DirectX3D)
映射變換定義了場(chǎng)景被怎樣投影到顯示器。最簡(jiǎn)單的產(chǎn)生投影矩陣的方法就是使用Matrix類的PerspectiveFovLH方法。它將會(huì)使用左手坐標(biāo)系創(chuàng)建一個(gè)正對(duì)場(chǎng)景的透視投影變換。(關(guān)于左右手坐標(biāo)系的詳細(xì)內(nèi)容請(qǐng)參見sdk,或你的高等數(shù)學(xué)、高等物理教材^_^)DirectX3D通常使用左手坐標(biāo)系。
以下是投影函數(shù)的簽名:
public static Matrix PerspectiveFovLH( float fieldOfViewY,float aspectRatio,float znearPlane,float zfarPlane);
投影變換描繪了場(chǎng)景的視見體(注:即可見部分)。視見體是由可視角度和前裁剪面(Near Plane)與后裁剪面(Far Plane)定義的一個(gè)平截頭體(注:比如四棱錐橫截面與底面之間的部分,上帝保佑,你還記得高中幾何),在這個(gè)平截頭體之內(nèi)的即是可見部分。函數(shù)頭里的nearPlane和farPlane兩個(gè)參數(shù),描繪了錐體的邊界:farPlane就是錐體的底面,而nearPlane則是橫截面。fieldOfView參數(shù)描繪了錐體的角度。aspectRatio類似于電視的高寬比,比如,寬銀幕電視的高寬比是1.85。你可以用可視區(qū)域的寬度來(lái)比上高度得出這個(gè)值。DirectX3D只繪制在這個(gè)平截頭體中的物體。
既然我沒從來(lái)沒有進(jìn)行過(guò)投影變換,也就根本不存在一個(gè)視見體,應(yīng)此DirectX3D什么也沒有繪制。但是,就算我們進(jìn)行了投影變換,我們還沒有進(jìn)行包含了攝像機(jī)信息的view transform。可以用一下函數(shù)完成這個(gè)任務(wù):
public static Matrix LookAtLH(Matrix pOut, Vector3 cameraPosition, Vector3 cameraTarget, Vector3 cameraUpVector);
僅僅通過(guò)各變量的名字你就可以知道如何使用這個(gè)函數(shù)。其中三個(gè)是用來(lái)描述攝像機(jī)的屬性:它的位置、它觀察點(diǎn)的位置以及一個(gè)被參考為“up”的方向。有了投影變換和view transform的幫助,DirectX3D已經(jīng)有足夠的信息來(lái)繪制三角了。添加代碼:(參見DirectX sdk Tutorial 3: Using Matrices中的SetupMatrices()函數(shù))
再運(yùn)行一次試試,哦,我們已經(jīng)有一個(gè)三角了,不過(guò)它完全是黑色的!問(wèn)題在哪呢?在沒有經(jīng)過(guò)變換的環(huán)境里,DirectX3D默認(rèn)使用燈光來(lái)計(jì)算場(chǎng)景中幾何體每一個(gè)象素的顏色,我們沒有定義燈光,也沒有額外的光照在三角上,So,它完全是黑色的。既然我們已經(jīng)為每一個(gè)點(diǎn)定義過(guò)了顏色,所以現(xiàn)在,可以安全并且簡(jiǎn)單的把場(chǎng)景里的燈關(guān)了。加上如下帶碼:
dev.RenderState.Lighting = false;
再試一次,終于,我們回到了未變換坐標(biāo)前的樣子。做了這么多改變到底有什么好處呢?最大的好處就是和在屏幕上直接繪制相比我們獲得了一個(gè)三維空間里的三角形——邁向偉大三維作品的第一步!^_^
既然有了三維空間里的三角,我們?cè)鯓幼霾拍茏屗雌饋?lái)確實(shí)是一個(gè)三維空間里的三角呢?最簡(jiǎn)單的事就是讓它旋轉(zhuǎn)起來(lái)。如何來(lái)做呢?很簡(jiǎn)單,我們只需要更改世界坐標(biāo)就可以了。
Device的世界坐標(biāo)變換會(huì)把每一個(gè)用局部坐標(biāo)定義的頂點(diǎn)位置轉(zhuǎn)換為用世界坐標(biāo)定義的頂點(diǎn)位置。(the world transform on the device is used to transform the objects being drawn from model space ,whice is where each vertex is defined with respect to the model, to world space,where each vertex is actually placed in the world.)Matrix對(duì)象的很多方法能完成這種變換:
device.Transform.World = Matrix.RotationZ( (float)Math.PI/6.0f );
它告訴DirectX3D除非指定一個(gè)新的世界坐標(biāo)變換,否則在這段代碼之后所有繪制的對(duì)象都將進(jìn)行這種變換。以上的世界坐標(biāo)變換是根據(jù)所給的弧度旋轉(zhuǎn)x軸。注意這里的參數(shù)必須是弧度而不是角度。有規(guī)率的改變參數(shù)的值就能讓三角形平滑的轉(zhuǎn)動(dòng)起來(lái)了(以下代碼略,參考sdk中的示例)。
我們旋轉(zhuǎn)的三角并不能給人留下深刻的印象。我們來(lái)試試讓他變得特別一點(diǎn),并且同時(shí)旋轉(zhuǎn)多個(gè)軸。很幸運(yùn),恰好有這樣一個(gè)方法,好了,更新代碼:
device.Transform.World = Matrix.RotationAxis( new Vector3(angle/((float)Math.PI*2.0f), angle/((float)Math.PI*4.0f), angle/((float)Math.PI*6.0f)), angle/((float)Math.PI);
這里使用了RotationAxis函數(shù),通過(guò)這個(gè)函數(shù),我們先定義了旋轉(zhuǎn)軸,并在每一維上用一個(gè)簡(jiǎn)單的式子不停改變軸的位置,然后再傳入三角形圍繞著軸旋轉(zhuǎn)的角度,就像我們先前做的一樣。
再次運(yùn)行程序,哦,我們確實(shí)得到了一個(gè)圍繞著旋轉(zhuǎn)軸轉(zhuǎn)動(dòng)的三角形,但似乎三角形會(huì)有規(guī)律的消失一陣,然后再顯示出來(lái)。好了,還記得我們先前提到的背面剔除(back face culling)嗎?這就是背面剔除在起作用的最好例子。當(dāng)DirectX3D渲染物體的時(shí)候,如果它發(fā)現(xiàn)某一個(gè)面沒有對(duì)著攝相機(jī),就不會(huì)繪制它,這就叫做背面剔除。那么程序在運(yùn)行時(shí),又是怎樣知道某一個(gè)特定的幾何面是否對(duì)著攝像機(jī)呢?快速的看看DirectX3D中的裁剪選項(xiàng)或許能給你一點(diǎn)提示。三種可用的剔除選項(xiàng)分別是:none,clockwise(順時(shí)針)以及counterclockwise(逆時(shí)針)。在clockwise以及counterclockwise的情況下,當(dāng)簡(jiǎn)單幾何體的頂點(diǎn)排列順序與剔除模式相反時(shí),它就不會(huì)被繪制。
看看我們的三角形,它的頂點(diǎn)是按逆時(shí)針順序來(lái)排列的(注:有關(guān)頂點(diǎn)的排列順序,可參考sdk文檔Face and Vertex Normal Vectors)。DirectX3D默認(rèn)的剔除模式就是逆時(shí)針模式。
你可以簡(jiǎn)單在頂點(diǎn)集合中把第一個(gè)和第三個(gè)元素交換一下,看看會(huì)有什么不同。
現(xiàn)在我們知道背面剔除是怎樣工作的,很顯然,我們簡(jiǎn)單的程序并不需要剔除功能。有一個(gè)簡(jiǎn)單的render state來(lái)控制剔除模式,添加如下代碼:
Device.RenderStates.CullMode = Cull.None;
再一次,erying works as expected,試試拖放窗口的大小會(huì)怎樣??
添上關(guān)于投影變換的圖片一張
攝像機(jī)位于o點(diǎn),視見體為ABCD--A'B'C'D',ABCD為后裁剪面,A'B'DC'D'前裁剪面
(第二部分完,下一次我們將要討論燈光了,并且解決拖放窗口時(shí)出現(xiàn)的問(wèn)題)
?
轉(zhuǎn)載于:https://www.cnblogs.com/yangbeibei/archive/2006/12/07/584927.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的深入Managed DirectX9(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: pku 1611 The Suspec
- 下一篇: 设计模式系列漫谈之五 - 迭代器模式