1. 程式人生 > >Direct3D學習筆記(四) 製作一個真正的三維空間

Direct3D學習筆記(四) 製作一個真正的三維空間

making our triangle three dimensional

回頭看看我們以前的程式,它看起來並不那麼三維。我們只是在windows視窗中畫了一個三角形而已,而這個用GDI是很容易做到的,現在我麼那要做的就是怎麼樣畫出一個物體來讓他看起來比較三維化,而這些,很容易在我們已有的程式中進行改進而得到。

如果你還記得,在早些時候當我們創造第一三角形的時候,我們使用了一種叫做轉換匹配(transformed coordinates)的東西,它能為螢幕所識別,並且我們很容易定義它。這些轉換非常普遍的應用在很多現代的3d遊戲中。

如果我們定義了這些匹配,我們必須在世界座標中定義每一個頂點而不僅僅是在螢幕區域作表中定義這麼簡單,你可以把世界座標想象成一個無限大的笛卡爾三維空間,你可以在這個空間的任何地方放置你想要放置的任何東西,好,現在讓我們來修改程式以完成繪製一個轉換後的三維的三角形。


首先,我們必須改變三角形頂點資料的格式,我們選用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].SetPosition(new Vector3(-1.0f, -1.0f, 1.0f));
verts[1].Color = System.Drawing.Color.Black.ToArgb();
verts[2].SetPosition(new Vector3(1.0f, -1.0f, 1.0f));
verts[2].Color = System.Drawing.Color.Purple.ToArgb();

並且要一起改變你的頂點格式的屬性

device.VertexFormat = CustomVertex.PositionColored.Format;

那上面做了什麼呢?如果你現在執行程式,會發現什麼改變都沒有發生。在我們領會到為什麼以前,然我們來稍微解釋一下上面的改變,你會發現,我們用PositionColored結構 代替了TransformedColored結構,用Vector3代替了Vector4這個類,這些新的結構儲存了圖形頂點的三維空間座標和頂點的顏色,而且我們必須要讓Direct3D我們要畫改變資料型別後的圖形,所以,我們還必須新增上最後一句讓Direct3D知道格式


我們既然已經改變了資料格式,但是為什麼我們的程式還是沒有任何顯示呢?原因是雖然我們告訴了Direct3D我們要畫的圖形的三維和顏色資訊,但是沒有告訴他要如何顯示這些資訊,也就是沒有告訴他從哪個位置來觀察我們畫的圖形,所以,我們必須新增一臺攝像機讓Direct3D知道在螢幕上顯示圖形的哪個地方。

攝像機必須經過兩種變換才能在裝置中被配置,每一種變換被定義成一個4*4的矩陣來傳遞給Direct3D,這個影射變化通常被定義成如何把真實場景變換到螢幕正確的顯示。最簡單的方法之一是使用Matrix類中的PerspectiveFovLH函式來完成這個轉換關係,這將在可視區域內用左手座標系統創造一個立體投影,在這個投影中的內容才會被顯示出來。至於什麼是左手座標系統,大家可以自己去查資料。。呵呵。在Direct3D中都是使用左手座標系統。

好,下面是我們對映矩陣函式的原型
public static Microsoft.DirectX.Matrix PerspectiveFovLH
(
System.Single fieldOfViewY ,
System.Single aspectRatio ,
System.Single znearPlane ,
System.Single zfarPlane
)

這個影射轉換描述的是一個場景中視覺範圍內的平截面,你可以把它想象成一個切掉了頭的金字塔,也就是一個四稜臺,在這個稜臺裡面的是你可以看見的區域,也就是顯示在螢幕中的區域,函式中的後兩個引數,近截面和元截面,分別描述了這個稜臺的前後界限,第二個引數描述了這個金字塔的角度的正切值,也就是我們常說的螢幕的長寬比例。當我們沒有設定我們對映轉換的時候,我們的可視區是看不到任何東西的,但是,就算我們設定了對映轉換,而沒有設定攝像機本身的一些屬性,我們一樣看不到東西,我們把這個設定攝像機本身屬性的過程叫檢視轉換(不知道這樣翻譯對不對 view transform),檢視轉換的函式原型如下

public static Microsoft.DirectX.Matrix LookAtLH(Microsoft.DirectX.Vector3 cameraPosition,
    Microsoft.DirectX.Vector3 cameraTarget , Microsoft.DirectX.Vector3 cameraUpVector )

這個函式比較容易理解,他的三個引數都是用來描述攝像機的屬性的,第一個表示攝像機的座標位置,第二個表示我們希望攝像機看到的物體,最後一個應該是個正方向。(The last argument is the direction that will be considered "up.")

通過對映轉換和檢視轉換,Direct3D現在有足夠的資訊來描繪我們需要的新三角形了,我們現在來修改前面的程式碼讓圖形正確的顯示出來吧,首先,我們加入一個"SetupCamera"的新函式,函式如下


private void SetupCamera()
{
    device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4,
         this.Width / this.Height, 1.0f, 100.0f);
    device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, 5.0f), new Vector3(),
         new Vector3(0,1,0));
}

現在你可以看到,我們在裝置中創造了一個對映變換,並且告訴了Direct3D我們的視覺區域,然後我們在裝置中創造了一個視覺轉換,讓Direct3D知道攝像機的一些基本屬性。然後在OnPaint函式中,清除完顯示器後呼叫它,用來初始化攝像機

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
            device.Clear(ClearFlags.Target, System.Drawing.Color.CornflowerBlue, 1.0f, 0);
            SetupCamera();
             CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3];
               。。。。
         }

現在我們可以再執行一下我們的程式了。

但是看起來好象不怎麼好,我們雖然已經畫出了一個三角形,但是它是全黑的,就算我們指定了他的顏色他也是黑的。問題出在pretransformed triangle和nontransformed triangle之間,我們前面做的都是已轉換系統的圖形,而現在我們是未轉換圖形,在未轉換系統中,Direct3D在預設條件下將使用我們定義的燈光來照亮物體以確定圖形的最終頂點的畫素顏色,但是我們在上面沒有確定外界光的顏色,也就是說沒有燈光照亮我們的物體,自然他就沒有顏色顯示而是黑色的了。我們以後將告訴大家怎麼定義外界光顏色,但是眼下,我們有個簡單的辦法解決這個問題,就是不要光,所有顏色將顯示我們定義的顏色而不是通過光計算出來的顏色,我們在SetupCamera的最後新增一行


device.RenderState.Lighting = false;
就可以了。

現在執行我們的程式,我們發現執行出來的東西和上一節的一模一樣,看起來我們做了這麼多工作,最後好像又回到了原地一樣,但是,實際上我們已經建立了一個完整的三維世界中的三角形,但是我們要讓使用者看起來真的覺得這是一個三維的世界,那麼我們還要做一些事情。

怎樣使我們畫的三角形看起來比較三維一點呢?最簡單的方法就是讓這個三角形旋轉一些角度,我們可以簡單的呼叫一些方法來實現這個角度的旋轉。

裝置中的世界變換是把我們真實世界的模型變換得在螢幕上看起來和我們看到的自然世界比較接近的一種變換(靠,這句英語太長了,大概意思就是這樣吧。。我看暈了),而且這個變換有很多種類,包括角度旋轉,比例尺寸的變化等等,我們這裡只要變換一個角度就可以了,在Matrix物件中有許多函式可以完成這樣的工作,我們在SetupCamera函式中新增下面的程式碼就可以了

device.Transform.World = Matrix.RotationZ((float)Math.PI / 6.0f);


這個程式碼是告訴Direct3D在這之後,每一個物體都將作改變,直到指定一個新的世界變換為止,在這裡,我們創造了一繞著z軸旋轉的變換,在這個函式中,所有的變數都必須是弧度而不是角度,好了,現在執行一下我們的程式,再和前面的進行比較,我們會發現已經不同了,物體繞z軸旋轉了一個角度了。

僅僅是這樣,似乎還是太簡單了,我們可以修改一下上面的函式讓物體繞z軸不斷的旋轉,這樣應該就有意思多了。

device.Transform.World = Matrix.RotationZ((System.Environment.TickCount / 450.0f)
    / (float)Math.PI);

好,現在執行一下我們的程式,會發現物體已經開始繞著z軸緩慢而且不停止的旋轉了,但是還有一個問題,我們看到的物體旋轉似乎有一點點跳躍,那是因為System.Environment.TickCount這個變數預設的步長是15毫秒,所以看起來會有點跳躍,不要著急,我們可以使用自己的變數來改變這個狀況。修改一下函式就可以了

device.Transform.World = Matrix.RotationZ(angle / (float)Math.PI);
angle += 0.1f;

注意,不要忘記在前面定義angle變數

好了,現在再執行一下,我們會發現物體的旋轉已經非常的平滑了,基本上達到了我們的需要,同樣,我們有時候不僅僅希望物體只繞一個軸旋轉,Direct3D已經為我們想到了很多,哈哈,我們可以這樣改寫這個函式為

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);


很明顯,這樣是告訴Direct3D讓物體繞著三個座標軸旋轉,執行一下,呵呵,物體是不是開始旋轉了阿,看起來是不是已經比較三維化了阿,不再是前面的那種平面的樣子了吧。。

最後還有一點,我們在三角形旋轉的時候有時候是看不見的,那麼我們在SetupCamera函式的最前面新增下面的程式碼就可以了

好,我們的第一個三維的三角形已經完成了。這樣,已經基本上算是一個真正的3d程式了吧,不要著急,以後還有更多的東西呢。有興趣的朋友可以耐心的等一等,我會堅持下去的,只是現在畢業設計也開始了,也要翻譯文章,我天天對著英文,頭都大了。。。呵呵,哦,我畢業設計是做“基於特徵子空間的數字水印技術”,要是有哪位朋友有這方面的資料請告訴我好吧。。哈哈,謝謝了。。。我的郵箱是[email protected]  QQ:128102  哈哈,謝謝,我不要源程式,只要一些資料和相關文件就可以了,謝謝啦。。。

相關推薦

Direct3D學習筆記 製作一個真正三維空間

making our triangle three dimensional回頭看看我們以前的程式,它看起來並不那麼三維。我們只是在windows視窗中畫了一個三角形而已,而這個用GDI是很容易做到的,現在我麼那要做的就是怎麼樣畫出一個物體來讓他看起來比較三維化,而這些,很容易

Unity學習筆記3-----製作一個模擬星系複雜版【Step1】

繼續學習Unity3D  這周任務之一是要做一個太陽系,如下圖: 而這次筆記的重點不在作業上~.~, 而是在於如何建立一個, 真正意義上的  “星系”。 上過課都知道, 作業簡單用以下兩條語句即可搞定: Planet.gameObject.transform.Rotat

caffe學習筆記--製作自己的資料集train.txt和val.txt,生成LMDB檔案

在深度學習的實際應用中,我們經常用到的原始資料是圖片檔案,如jpg,png,tif等格式的,而且有可能圖片的大小還不一致。 我今天嘗試製作一個自己的訓練資料集,主要步驟為: 1.用MATLAB截圖得到訓練集的圖片 2.生成標籤檔案列表,即生成 train.

Unity學習筆記3-----製作一個模擬星系複雜版【Step3】

行星的軌道離心率普遍較低。 首先來看傾斜角的問題。 前面提到過, 只要將行星產生的位置約束於X軸附近, 再加上初始受到的動量方向, 就可以基本控制住行星運動的傾角。兩個函式程式碼如下: Vector3 ProperArea(float min, float max) { float x = (max

前端學習筆記--CSS控制UL LI 的樣式詳解(推薦)及純CSS製作各種各樣的網頁圖示三角形、暫停按鈕、下載箭頭、加號等

DIV+CSS裡,我們用得最多的就是ul li來顯示資料,如新聞按鈕等。下面給大家一個css ul li的例子供學習<div id="menu"> <ul> <li><a href="#">首頁</a></

Cocos2d-x學習筆記 布景層的加入移除

dcl from position 顏色 顯示地圖 idt col 分享 學習 布景層類也就是CCLayer類,每一個遊戲場景中都能夠有非常多層,每一層負責各自的任務。顯示地圖、顯示人物等。同一時候層還是一個容器,能夠放入文本、圖片和菜單。構成遊戲中一個個UI。這次

機器學習筆記機器學習可行性分析

資料 表示 image 隨機 訓練樣本 -s mage 例如 lin 從大量數據中抽取出一些樣本,例如,從大量彈珠中隨機抽取出一些樣本,總的樣本中橘色彈珠的比例為,抽取出的樣本中橘色彈珠的比例為,這兩個比例的值相差很大的幾率很小,數學公式表示為: 用抽取到的樣本作為訓練

Python_sklearn機器學習學習筆記decision_tree決策樹

min n) 空間 strong output epo from 標簽 ict # 決策樹 import pandas as pd from sklearn.tree import DecisionTreeClassifier from sklearn.

Python學習筆記 列表生成式_生成器

rec triangle 小寫 ont 無限 end clas 普通 執行過程 筆記摘抄來自:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431

Unity3D之Mecanim動畫系統學習筆記:Animation State

大致 面板 輸入 jpg any 動畫播放 速度 nsf 顯示 動畫的設置 我們先看看Animation Clip的一些設置: Loop time:動畫是否循環播放。 下面出現了3個大致一樣的選項: Root Transform Rotation:表示為播放動畫

.net core 2.0學習筆記:遷移.net framework 工程到.net core

編譯 its evel hashtable ref 學習筆記 inline null 創建 在遷移.net core的過程中,第一步就是要把.net framework 工程的目標框架改為.net core2.0,但是官網卻沒有提供轉換工具,需要我們自己動手完成了

ES6學習筆記—— async 函數

ons fst cte code span pre getname 普通 聲明 await 是 async wait 的簡寫, 是 generator 函數的語法糖。 async 函數的特點: async 聲明一個方法是異步的,await 則等待這個異步方法執行的完

Hibernate學習筆記 --- 映射基本數據類型的List集合

varchar prim drop n) 進行 lis auth pos 方案 集合按其內元素的數據類型分為兩種:基本數據類型集合及復雜對象類型集合,Hibernate對於兩類集合提供不同的映射方式。(在類上以@Embeddable註解的復雜對象數據類型處理方式同基本數據類

java學習筆記:import語法

employee sign cnblogs java 調用 變量賦值 temp 職位 求職 Import 語法是給編譯器尋找特定類的適當位置的一種方法。 創建一個Employee 類,包括四個實體變量姓名(name),年齡(age),職位(designation)和薪水(s

Cesium學習筆記Camera

ttr can str efault 簡單的 list 事件處理 get provider http://blog.csdn.net/HobHunter/article/details/74909641 Cesium 相機控制場景中的視野。操作相機的方法有很多,如

python學習筆記-數據類型

rand 兩個 urn 浪費 line 平年 randint .com .cn 0. 在 Python 中的數據類型詳解 http://www.cnblogs.com/scios/p/8026576.html 1. 為什麽布爾類型(bool)的 True 和 False 分

Nodejs學習筆記-----Buffer

pretty 成員 保存 n) tin 設置 amp 個數 普通 Node.js Buffer(緩沖區) JavaScript 語言自身只有字符串數據類型,沒有二進制數據類型。 但在處理像TCP流或文件流時,必須使用到二進制數據。因此在 Node.js中,定義了一個 Buf

Elasticsearch學習筆記ElasticSearch分布式機制

clas cse 負載均衡 丟失 數據 不可 分布式 復雜 發生 一、Elasticsearch對復雜分布式機制透明的隱藏特性 1、分片機制: (1)index包含多個shard,每個shard都是一個最小工作單元,承載部分數據,lucen

DeepLearning.ai學習筆記卷積神經網絡 -- week1 卷積神經網絡基礎知識介紹

除了 lock 還需要 情況 好處 計算公式 max 位置 網絡基礎 一、計算機視覺 如圖示,之前課程中介紹的都是64* 64 3的圖像,而一旦圖像質量增加,例如變成1000 1000 * 3的時候那麽此時的神經網絡的計算量會巨大,顯然這不現實。所以需要引入其他的方法來

python學習筆記字符串及字符串操作

默認 小寫字母 是不是 swap git 查找字符 英文 去掉 title 字符串   字符串可以存任意類型的字符串,比如名字,一句話等等。 字符串還有很多內置方法,對字符串進行操作,常用的方法如下: 1 name1=‘hello world‘ 2 print(nam