xna4.0,ps2.0,PC平台使用hlsl定義結構體:
struct VS_INPUT
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float3 Normal : NORMAL0;
float3 Tangent : TANGENT0;
float4 BoneIndices : BLENDINDICES0;
float4 BoneWeights : BLENDWEIGHT0;
}
載入一個簡單的貼圖mesh,調用Bump相關pass時,運行時在
mesh.Draw();
處跳出異常:
The current vertex declaration does not include all the elements required by the current vertex shader. Tangent0 is missing.
問題就在於這個切線數據 Tangent 丟失。
外事不決問google,找到答案。
到Content項目中將默認為false的“Generate Tangent Frames”項目置為true,編譯後約多出10%容量,問題解決。
貌似3.1時默認是開啟的,可能因為大多數model不用到切線數據,所以4.0不再默認生成。
- 12月 07 週三 201121:38
XNA 切線數據 Tangent 丟失 record
- 12月 07 週三 201110:30
C# 無蝦米線上查碼程式
無蝦米線上查碼程式,最近常在查碼,覺得內建的不好用,所以自己就寫了一個,要用這個軟體一定要有網路喔!!
這個程式最大的功能在於他可以自動記錄你之前查過的字。
下載網址:
http://redtreeonline.com/other/check.zip
- 10月 19 週三 201117:34
C# 計算兩個時間間隔 record
計算兩個時間間隔:
DateTime t1=DateTime.Now;
sleep(20000)
double ans = (DateTime.Now - t1).toMimiSecond
- 8月 11 週四 201117:24
DirectX 3D MAX 插件編寫 INode常用操作
// 當前節點添加子節點
void INode::AttachChild()
// 當前節點從父節點脫離
void INode::Detach()
// 得到當前節點的父節點
INode* INode::GetParentNode()
// 返回當前節點的子節點數
int INode::NumberOfChildren()
// 返回第i個子節點
INode* INode::GetChildNode()
// 確實當前節點是否是根節點
int INode::IsRootNode()
// 設置骨骼開啟和關閉 如:maxscript: $.boneEnable = true
void INode::SetBoneNodeOnOff()
// 隱藏節點
void INode::Hide()
// 得到節點是否隱藏
int INode::IsObjectHidden()
// 刪除節點
void INode::Delete()
// 得到指定時刻節點變換矩陣
void INode::GetNodeTM()
// 設置指定時刻節點變換矩陣
void INode::SetNodeTM()
// 得到節點變換矩陣
Matrix3 INode::GetObjectTM();
// 選擇節點
Interface::SelectNode(INode *node)
// 取消選擇的節點
Interface::DeSelectNode(INode *node)
// 選擇或取消一系列節點(INodeTab)
Interface::SelectNodeTab(INodeTab &nodes)
// 取消所有節點的選取
Interface::ClearNodeSelection()
- 8月 11 週四 201114:37
DirectX 3DMax SDK的基本概念 介紹
3DMax SDK的基本概念 介紹
這一部分對SDK的概念進行簡單的介紹,提供很多基本的介紹以便開發者創建插件應用程序.更多的信息請參看下面的鏈接.
二、插件體系概述
三、3DS MAX中的插件
五、場景中結點與物體的關係
七、時刻和時間間隔
九、參數塊
十一、DLL函數
十二、創建插件和運行的類型ID標識 3DS MAX插件主要用來建模,動畫和渲染.這些插件主要繼承於下面幾個抽象基類之一.
Anomatable->ReferenceMaker->ReferenceTarget 1.Animatable
類層次中最基本的層次是關於動畫的抽象類,為Animatable類.這個類主要的方法是軌跡視圖中顯示的功能和內存管理.從Animatable類繼承的兩個類用以在3DS MAX中的各不同部分進行交互.
2.ReferenceMaker
當3DS MAX中的一個引用被創建,創建引用的物體就會對創建引用的目標物體存在依賴性.引用創建者是一個依賴的物體,引用目標是獨立的物體.當一個引用目標的狀態發生改變時,引用目標需要通知引用創建者它的改變.屬於引用創建者的任何類都必須從抽象類ReferenceMaker類繼承.
3.ReferenceTarget
任何屬於引用目標的類必須從抽象類ReferenceTarget類繼承.見上面ReferenceMaker的解釋.
>>不從這些類繼承的插件
這些插件不從三個抽象基類繼承,一般來說,這些類不直接與動畫相關.比如,導入導出插件僅僅從3DS MAX中導入和導出數據,因此,它們不會出現在軌跡視圖中,且它們的函數獨立於其它插件.
SDK中的大部分類都是從抽象基類繼承過來的.
三個抽象基類的根類是Animatable類,它定義了動畫和軌跡視圖相關的大部分方法.
從Animatable類繼承的類是ReferenceMaker,這個類允許對其它物體創建引用.
從ReferenceTarget類繼承的類是ReferenceTarget,一個引用是場景中兩個物體的雙向連接,它創建"ReferenceMaker"和"ReferenceTarget"之間正式的依賴性記錄.它的主要功能是使一個引用目標在自身狀態發生改變時,通知依賴於它的引用者.
不從Animatable繼承的類主要是那些與動畫不相關的類.比如,Interface類提供了一系列方法來調用3DS MAX自身的函數,而Interface類並不繼承於Animatable類.
下圖顯示了SDK中主要公共類的繼承圖,最基本的類(即沒有父類的類)顯示在最上面,繼承層次向下和向右.
圖略(參看SDK)
三.3DS MAX中的插件
這一部分討論3ds max調用插件方法的途徑和插件調用3DS MAX提供的方法的途徑.
>>用戶實現的方法
每個插件都從3DS MAX的一個基類繼承下來的,比如,創建一個幾何物體的插件可以從SimpleObject2類繼承.
class MyGeomObject:public SimpleObject2 //... 3DS MAX中定義SimpleObject2類的頭文件是simpobj.h.插件開發者必須實現SimpleObject2類中的某些方法,換句話說,插件覆蓋父類的一些方法.3DS MAX能夠調用插件中的這些方法.
比如,SimpleObject2的BuildMesh()方法,3DS MAX調用該方法得到幾何物體的三角網格,插件要實現SimpleObject2::BuildMesh()以產生3ds max所需要的網格.
>>基類方法 比如,一個基本幾何物體可能從GeomObject繼承,這個基本集合體可以調用NotifyDependents(),這是ReferenceTarget的一個方法,這個方法繼承於基類(GeomObject->Object->BaseObject->ReferenceTarget).
>>接口方法
插件也可以調用3DS MAX的方法,通過Interface類提供的接口指針.接口類僅僅是一個沒有成員變量並只包含純虛函數的類.類似於這樣的類本質上都不過是一個函數指針表.
接口類在3ds max中經常使用,最經常使用的接口類是Interface,指向該類的指針可以調用很多方法,插件用這個指針實現3DS MAX提供的一些普通操作.比如,當一個修改器插件想在命令面板上顯示用戶接口時可以調用Interface的AddRollupPage()方法,或者插件想得到3DS MAX幀滑塊指定的當前時間可以調用Interface的GetTime()方法.
在面向對象的示例中,相互獨立的插件物體協同工作以實現系統的全部功能,因此內部物體需要進行通信.3DS MAX中利用引用結構作為控制通信的體系結構.
>>個案研究 3DS MAX動畫控制器有一個Look At插件(注視約束插件),這是一個空間變換控制器,它可以控制其在場景中的位置,旋轉,縮放.Look At控制器旋轉它所屬的項目以使其朝向(或注視)另一個物體.比如,創建一個自由相機並且指定一個Look At控制器作為相機的空間變換控制器,然後在場景中選擇一個Box作為Look At控制器的目標,這會使自由相機旋轉以至其方向正對於Box.無論何時,只要Box移動,控制器就會重新設置以使相機仍然指向Box.當然,如果從場景中刪除Box,攝像機將能識別並保持不動.
現在考慮這些項目(攝像機,Look At控制器,Box)都是插件,每個插件與其它插件都沒有關係,那麼它們之間是怎麼通信的呢?比如,攝像機怎麼知道在Box移動的時候需要改變自己的方向?Look At控制器怎麼知道場景中的Box被刪除?這些物體進行通信的答案就是References(引用).
>>Reference引用
一個引用是聯合兩個項目的方法,此時一個項目被認為依賴於另一個項目.在上面的例子中,Look At控制器依賴於Box,攝像機依賴於Look At控制器.也就是說,如果Box發生改變它需要讓依賴於它的其它物體知道這些改變.控制器通過引用,得到Box發生改變的通知.控制器通過同樣的方式通知依賴於它的項目.當控制器發生改變時,它讓依賴於它的項目知道,於是,攝像機得到通知.
一個物體通過創建引用建立依賴關係,當一個物體創建一個引用,就被稱為引用創建者,那些被依賴的物體被稱之為引用目標.在上面的例子裡,攝像機是引用創建者,它引用Look At控制器,那麼Look At控制器就是攝像機的引用目標;同時Look At也是引用創建者,它引用Box,Box是控制器的引用目標.實際上,Box有它自己的引用,比如,它的空間變換控制器.
3DS MAX存在很多內部創建的引用,在一個簡單的場景中,可能存在數十個引用(很多為3DS MAX內部使用),而在一個複雜的場景中,可能存在數百個引用.
場景中每一個物體都關聯一個結點,場景中結點和物體存在著一一對應的關係.球,網格,攝像機,燈光和輔助物體都是場景中的物體,所有這些物體能可以被變換,旋轉等等. (1)結點的空間變換控制器控制物體在場景中的位置,旋轉,縮放.
(2)渲染器使用結點的材質來設置物體的表面特徵,比如顏色,紋理,凹凸.
(3)層次信息用來控制物體的連接/未連接狀態和反向動力學(IK). 程序物體是視口中用戶能夠創建和控制的物體.比如包括攝像機,燈光,幾何物體(長方體,球,或者更複雜的物體). 幾何物體必須最終轉換為三角網格,以便可以渲染.但3DS MAX渲染器和光線跟蹤渲染(mental ray renderer)都是工作在MESH物體級別下.所以基本物體,布爾物體,閣樓,粒子系統,面片柵格,NURBS曲面都必須轉換為三角網格.只有一個例外:光線跟蹤支持一個指定的基本體頭髮,並且比三角網格更為有效. 對於一個程序物體,3DS MAX提供修改器來擴展物體.可以對物體應用修改器進行適當的修改,變形,處理和編輯.用戶也能夠利用空間彎曲插件來改變幾何體的世界空間位置.對於插件開發者而言,所有這些功能的實現都必須要理解從參數物體到可修改的三角面片模型的轉換過程.
3DS MAX的幾何管道系統用來控制這些處理和轉換.幾何管道系統是用來使參數物體可以被修改器修改,最後產生一個適合的三角網格模型用來渲染和在視口中顯示. >>時間點
3DS MAX中基本的時間單位是Timue.SDK中在任何需要指定時間點的時候使用Timue.1Timue等於1/4800秒.
Timue同樣是一個3ds max數據類型.
比如,如果插件需要知道當前的系統時間(在3DS MAX中以幀滑塊表示),可以調用Interface::GetTime().這個方法返回當前的時間(以Timue為單位,即1/4800s).
>>時間間隔
在3ds max中,時間間隔(Interval類)通常被用來定義一個時間段,在這個時間段內物體不發生改變.為了盡可能快,3DS MAX避免在任何時候重新評估計算物體.如果一個動畫插件可以指定多長時間內它不發生改變,3DS MAX就可以知道它不用在這段時間內重新評估計算物體.
比如,3DS MAX需要知道在多長時間內修改器的修改是有效的.以彎曲修改器在100幀的動畫中為例,用戶改變彎曲的角度,並標誌在第0幀到第50幀內不彎曲,在50-100幀時彎曲45度.則在前50幀內,3DS MAX不需要重新評估計算修改器(畢竟,在前50幀不彎曲).3DS MAX用有效時間間隔來標識什麼時間段是變形的有效時間.有效時間間隔是一個時間段,比如在23幀處返回的有效時間間隔可能是FOREVER,在56幀返回的有效時間間隔可能是瞬時的.
3DS MAX中所有的動畫都由一個稱之為Animtable controller(動畫控制器)的插件管理,或者簡稱為控制器. 其它控制器是基於程序的,在特定的時間點編程狀態下設置其值(比如噪波控制器用不規則的碎片形功能計算其值). (1)浮點值(float)
(2)三個浮點值(Point3)
(3)位置(Matrix3)
(4)旋轉(Quat)
(5)縮放(Scalue)
(6)變換(Matrix3) 許多控制器用的參數變量,比如一個程序球的半徑參數變量.3DS MAX提供給開發者工具,使用參數變量以更容易地管理它們.最重要的是參數塊. 參數塊非常重要,它用來存儲和顯示插件的變量值.
對於插件和用戶交互所需要的數據,3DS MAX提供存儲,獲取和顯示這些數據的類.大多數插件以對話框的形式顯示信息,並且用戶可以控制這些顯示信息(比如定義一個程序物體的參數).
參數塊存儲插件使用的變量(通常稱之為參數),同時管理撤銷/重做功能,並自動提供這些參數給MAXScript,同時管理引用系統中的消息通知.
參數塊在相關類的協同下自動地將數據顯示到3DS MAX的用戶接口,這將開發者從繁瑣的底層任務中解脫出來.
用戶同3DS MAX的交互主要通過命令面板的卷展欄和對話框,鼠標(或者寫字板),鍵盤,和3D視口.SDK提供給開發者控制每個用戶交互的區域. (1)卷展欄:體現於材質編輯器,環境,和渲染對話框中.
(2)模態對話框
(3)非模態對話框
>>控制
對話框或卷展欄中許多按鈕,微調控制項,編輯區域等都來自於3DS MAX的Custom Control.這幫助3DS MAX中各個插件的圖形接口外觀一致.
>>鼠標
鼠標與視口交互在SDK中通過Command Modes(命令模式)控制.
>>鍵盤 >>視口
插件經常需要在3D視口中繪製以顯示其內容或其它小物件,可以通過調用交互渲染器(GraphicsWindow類)提供的方法.十一、DLL函數
這一部分介紹每一個插件DLL都需要的五個函數,更多詳情參閱Required DLL Functions(Detailed).
每一個插件開發者需要提供DllMain的代碼,和四個Lib函數,下面簡單地描述這幾個函數:
>>函數初始化
DllMain() 這個函數是Windows用來初始化DLL的鉤子程序,3DS MAX插件使用該函數來初始化一般的控制庫和3DS MAX定制的控制.
>>3DS MAX管理和給DLL插件歸類的函數
這四個函數描述了DLL提供的插件的數目和屬性.
(1)LibNumberClasses() 該函數返回DLL中插件類的數目.
(2)LibVersion() 該函數允許系統處理DLL插件的廢置版本.
(3)LibDescription() 這個函數返回給用戶一個文本字符串,如果該DLL是不可用的.
(4)LibClassDesc(i) 這個函數返回一個descriptor類對象的指針,這是一個類描述符,每個DLL插件類都有該描述符對象,一個類描述符有以下功能:
a)描述每個插件類的屬性;
b)創建插件類;
c)銷毀插件類.
開發者可以在一個DLL文件中放置多個插件,在這種情況下,LibClassDesc()將會執行一個switch語句,並返回不同的類描述符指針.十二、創建插件和運行的類型ID標識
Descriptor類繼承於ClassDesc2,它有幾個重要的用途,但最重要的兩個是該插件的分類,和為該插件實例分配內存.
一個DLL插件包括許多插件類,在運行時,3DS MAX通過LibNumberClasses函數調用DLL,以確定其包含多少個插件類.然後根據插件類的個數,循環調用靜態的描述符類(調用LibClassDesc(i)).Max得到類描述符後,通過調用類描述符的Create()方法分配插件的實例.
每一個插件類都必須有一個類標識(ClassID).
每個插件對象關聯兩個類標識(2 IDS),它們是:
(1)Class ID唯一標識一個插件類
(2)Super Class ID指定插件類的超類.
>>例子
比如,一個球對象有一個唯一的Class ID,可以簡單地通過SDK提供的程序字哦那個生成這個ID,它唯一標識該插件類.(該程序在\MAXSDK\HELP\GENCID.EXE)
它的超類ID是GEOMOBJECT_CLASS_ID,因為它屬於基本幾何體.超類IDS由MAX定義,每個插件都必須屬於其中的一個分類.
比如,所有的紋理貼圖插件都有相同的超類ID,為TEXMAP_CLASS_ID.每個單獨的紋理貼圖插件都有它自己唯一的類標識符ID.因此,超類ID定義該插件屬於哪一個分類(這裡是紋理貼圖插件),而類ID唯一標識一個特定的插件類.
>>運行時類型ID
類描述符的方法ClassDesc::SuperClassID()返回超類ID,ClassDesc::ClassID()返回類ID.
>>創建插件
類描述符的另一個函數是為插件類實例分配內存.比如,當裝載一個3DS MAX文件,該文件包含一個程序球,3DS MAX需要創建一個球插件的實例.它通過調用球的類描述符ClassDesc::Create()實現.
- 8月 10 週三 201110:10
DirectX MAX SDK的INode的變換矩陣,以及Object的一些常識
MAX SDK中,INode是很重要的一個部分。 幾乎所有的東西都需要通過INode來訪問:例如Mesh、Camera等.
下面我來簡單的介紹一下和INode相關的各種不同的TM.(Transformation Matrix).僅僅代表我近日閱讀MAX SDK的一些理解.希望高手指教.新手討論.
TM.(Transformation Matrix)
首先是介紹一下Node和Object(Mesh TriObject等).
MAX裡的Scene是由INode構成的,Node裡包含很多東西.這個Node可能是可以Deform(變形)的,或者是不可以Deform的。如常見的Editable Mesh 和Cylinder一類的東西是可以Deform的Node. 而Camera是不可以Deform的。
一個包含了幾何物體的Node(就是可以轉化為GeomObject的)中的幾何體並不是 Node 本身.而是 Node 中的 Object .這個 Object 可能是一個 Derived Object(表示這個Object從別的Object那裡派生出來,通常是從上一個修改器(Modifier)的結果那裡派生的).
<< 另一解釋:
一個 Node 包含幾何物體(就是可以轉化為GeomObject的),這個幾何物體就是 Object , 這個 Object 可能是一個 Derived Object(表示這個Object從別的Object那裡派生出來,通常是從上一個修改器(Modifier)的結果那裡派生的). >>
同時還附加了一些 Modefier ,每個 Modifer 的修改結果都是一個 Deried Object .而類似 Pyhsique 的修改器都是作用在 Derived Object上.因此,
要找一個 Node 有沒有 Pyhsique 的修改器,需要通過 Derived Object 來得到.
INode->GetObjectRef()可以得到這個物體的Object .
Object->SuperClassID() == GEN_DERIVED_CLASS_ID的話,就表示這個Object是一個Derived Object .
DerivedObject->GetObjectRef()得到這個這個Derived Object是從那個Object派生出來的..
用上面三個函數.可以遍歷一個Node從創建到形成這個Node,所有經過的Derived Object.
INode->EvalWorldState() 得到這個Node上最終的Object的狀態(ObjectState.它包含了Node的Object),把頂點變換到世界坐標系中來
下面.我來介紹Node裡容易引起混淆的幾個TM. TM.(Transformation Matrix)
INode->GetNodeTM().: NodeTM()只包含了Node的TM.不是物體的TM. 每個Node都有個基準點(Pivot Point). 這個Pivot Point在世界坐標中的狀態,就是這個Node的TM. 而附加在這個Node上的Object相對這個 Pivot Point 可能會有其他的變換(平一,旋轉等). 所以. NodeTM 不能用來變換 Object.
INode->GetParentTM(). 父節點的TM
我們說過NodeTM是在世界坐標中的。所以,要得到節點相對父節點的TM需要 GetNodeTM()*Inverse(GetParentTM()).
GetNodeTM()*Inverse(GetParentTM())//得到節點相對父節點的TM
INode->GetObjectTM(). 用這個矩陣,可以把Node中的Object變換到世界空間來.其實GetObjectTM() = NodeTM() * (Object相對於Node的變換).
INode->GetObjTMAfterWSM() : WSM的意思是World Space Modifer.
Modifer有兩種,一種是Object Space的。一種是World Space的.如名字所暗示的:
World Space Modifier要把Object先變換到世界空間裡來.而不是物體空間中,所以,如果一個Object(Node上的Object)受到過World Space Modifier的影響。
我們在EvalWorldState()的時候已經把頂點變換到世界坐標系中來了。
GetObjectTM 返回的將是把 Object 從 INode 的局部坐標系變換到世界坐標系的矩陣, 如果把 ObjectTM 乘上得到的頂點(經過WSM後,頂點已經在世界空間中了),就做了兩次世界變換了,所以我們需要得到 Node 的一個矩陣,這個矩陣是表示能把經過 WSM 變換後的頂點正確的變換到世界空間中來. 這個矩陣就是GetObjTMAfterWSM().
如果一個INode上沒有WSM. 那麼GetObjTMAfterWSM()和GetObjectTM是相同的.同樣,它和GetObjTMBeforeWSM也是相同的。
INode->GetObjTMBeforeWSM() : 這個函數的到WSM施加在INode前的ObjectTM.即這個INode不包括WSM時候,把它的Object的頂點變換到世界坐標系中的變換矩陣..
以上只是本人的拙見.參考了MAX SDK中的:
The Node and Object Offset Transformations
Geometry Pipeline System
的兩個部分.
- 7月 06 週三 201110:45
DirectX D3DPRESENT_PARAMETERS 參數說明
D3DPRESENT_PARAMETERS 參數說明
struct D3DPRESENT_PARAMETERS{
UINT BackBufferWidth;
UINT BackBufferHeight;
D3DFORMAT BackBufferFormat;
UINT BackBufferCount;
D3DMULTISAMPLE_TYPE MultiSampleType;
DWORD MultiSampleQuality;
D3DSWAPEFFECT SwapEffect;
HWND hDeviceWindow;
BOOL Windowed;
BOOL EnableAutoDepthStencil;
D3DFORMAT AutoDepthStencilFormat;
DWORD Flags;
UINT FullScreen_RefreshRateInHz;
UINT PresentationInterval;
};
BackBufferWidth和BackBufferHeight:
後備緩衝的寬度和高度。在全屏模式下,這兩者的值必需符合顯卡所支持的分辨率。例如(800,600),(640,480)。
BackBufferFormat:
後備緩衝的格式。這個參數是一個D3DFORMAT枚舉類型,它的值有很多種,例如D3DFMT_R5G6B5、D3DFMT_X8R8G8B8為遊戲後備緩衝常用格式,這說明後備緩衝的格式是每個像素16位,其實紅色(R)占5位,綠色(G)占6位,藍色(B)占5位,為什麼綠色會多一位呢?據說是因為人的眼睛對綠色比較敏感。
- 7月 04 週一 201110:15
DirectX D3DXLoadMeshFromX
使用下面的函數加載存儲在.x文件中的Mesh數據。它創建一個ID3DXMesh對象,然後從.x文件中讀取Mesh的幾何信息。
HRESULT WINAPI
D3DXLoadMeshFromX(
LPCTSTR pFilename,
DWORD Options,
LPDIRECT3DDEVICE9 pD3DDevice,
LPD3DXBUFFER *ppAdjacency,
LPD3DXBUFFER *ppMaterials,
LPD3DXBUFFER *ppEffectInstances,
DWORD *pNumMaterials,
LPD3DXMESH *ppMesh
);
pFileName –.x文件的文件名
Options –創建Mesh的標誌。詳情可參考SDK文檔中的D3DXMESH枚舉類型。常用的幾個標誌如下:
D3DXMESH_32BIT –使用32位的頂點索引,默認為16位
D3DXMESH_MANAGED –使用受控的內存緩衝池
D3DXMESH_WRITEONLY –緩衝區只可執行寫操作
D3DXMESH_DYNAMIC –使用動態內存緩衝池
pD3DDevice –D3D設備指針
ppAdjacency –使用ID3DXBuffer返回Mesh的鄰接信息,這是一個DWORD數組
ppMaterials –使用ID3DXBuffer返回Mesh的材質數據,這是一個D3DXMATERIAL類型數組
ppEffectInstances –使用ID3DXBuffer返回一個D3DXEFFECTINSTANCE結構數組
pNumMaterials –返回Mesh對象的材質數量,也就是通過ppMaterials返回的D3DXMATERIAL數組的元素數
ppMesh –返回ID3DXMesh對象
- 7月 01 週五 201110:54
DirectX Chapter 5: 3D Primitives and Vertex Buffers
Chapter 5: 3D Primitives and Vertex Buffers
When we want Direct3D to render a 3D object for us, we start off by defining that object as a collection of vertices. We then give the object a more solid feel by connecting the vertices together with line segments.
The vertices define the model in 3D space and the line segments define the object's outer skin or surface by joining the vertices together in groups.
當我們想的Direct3D渲染3D對象對我們來說,我們開始定義的對象作為一個集合的頂點。然後,我們給對象更加堅實的感覺通過連接頂點與線段。
頂點定義模型在三維空間中的線段定義對象的外表面由皮膚或加入頂點一起群體。
At first, this seems simple enough but many beginners become confused once they realize that 3D objects are defined completely by their vertices, We never actually define the object's surface by saying, “connect this vertex to that vertex with a line”.
起初,這看起來簡單,但很多初學者成為困惑一旦他們認識到3D對象的定義完全被他們的頂點,我們從未真正確定物體表面的說,“這個頂點連接到該頂點與一條線”。
So, where do these line segments come from if we don't actually define them? Well, the line segments are simply implied by vertex order and a set of predefined rules for geometry construction which have been laid down by Direct3D.
那麼,做這些線段來,如果我們不從實際定義呢?
那麼,線段只是隱含頂點秩序和一組預定義的規則的幾何結構已訂下的Direct3D。
These rules are basically defined through what is called a, “3D primitive”, which is a collection of vertices that form a single 3-D entity.
這些規則是基本確定通過所謂的“3D原始”,這是一個集合的頂點,形成一個三維實體。
When we define a 3D object we need to pick the 3D primitive we want to use and define our object's vertices accordingly so Direct3D can interpret them correctly during rendering.
當我們定義一個3D對象,我們需要選擇我們想要的3D原始的使用和定義我們的對象的頂點因此可以這樣解釋他們的Direct3D過程中正確渲染。
Of course, half of these 3D primitives deal specifically with triangles, which I've already described as being the basic building block and work-horse of modern 3D graphics.
當然,這些 3D基本類型的一半專門處理三角形,我已經描述為基本構件和工作馬現代三維圖形。
The other 3D primitives deal with points and lines, which can be very useful in creating special tools like model and level editors where an artist or modeler may need to manipulate the actual vertices and edges of model's geometry.
其他三維基本類型處理點和線,這是非常有用的工具,如建立專門的編輯模式和水平在一個藝術家或建模可能需要處理的實際頂點和邊模型的幾何形狀。
In all, Direct3D defines six 3D primitives:
總之,Direct3D的三維基本類型定義了六個:
Point Lists
Line Lists
Line Strips
Triangle Lists
Triangle Strips
Triangle Fans
點名單
行列出
條線
三角列表
三角形帶
三角風扇
Direct3D gives each primitive type an enumerated name, which is defined under the D3DPRIMITIVETYPE data type like so:
Direct3D的為每個原始類型枚舉的名稱,是指在 D3DPRIMITIVETYPE 數據類型,象這樣:
typedef enum _D3DPRIMITIVETYPE {
D3DPT_POINTLIST = 1,
D3DPT_LINELIST = 2,
D3DPT_LINESTRIP = 3,
D3DPT_TRIANGLELIST = 4,
D3DPT_TRIANGLESTRIP = 5,
D3DPT_TRIANGLEFAN = 6,
D3DPT_FORCE_DWORD = 0x7fffffff
} D3DPRIMITIVETYPE;
Point Lists
A point is the simplest of all primitives. If our buffer of vertices is treated as a point list, then each vertex is nothing more than a point in 3D space and no attempt will be made to connect the vertices with edges.
Obviously, this primitive is seldom used since it's difficult to render any thing of interest with it.
點列表
A點是最簡單的所有基元。如果我們的頂點緩衝被視為一個點的列表,然後每個頂點無非是在三維空間中的點,也沒有試圖將作出連接頂點與邊。
顯然,這種原始的是很少使用,因為它很難提供任何東西與它的利益。
Line Lists
In a line list, our vertices are used to create isolated and unconnected line segments. For example, if we call the first four vertices in the buffer v0, v1, v2, and v3; then v0 and v1 defines the first line segment, and v2 and v3 define the second line segment.
線列表
在線路列表,我們的頂點用於創建孤立的和未連接線段。
例如,如果我們所說的前四個頂點緩衝區中的V0,V1,V2和v3,然後 V0和V1定義的第一行段,和v2和v3定義第二個線段。
Because line lists pair-up vertices to make line segments, we can not use this primitive with vertex buffers that contain an odd number of vertices.
因為線列表對行動的頂點,使線段,我們不能用這種原始的頂點緩衝區包含一個奇數的頂點。
Line Strips
A line strip is similar to a line list, but instead of rendering a collection of isolated line segments, which may or may not be touching a line strip renders a series of connected line segments by simply connecting each vertex to the last one with an edge.
線條
一條線地帶類似於行列表,而是呈現一個集合的孤立線段,這可能會或可能不會接觸線地帶呈現一系列連接的線段,只需連接每個頂點到最後一個與邊緣。
- 6月 30 週四 201111:56
DirectX D3DLIGHT9
Direct3D基礎-燈光 D3DLIGHT9
在D3D中有3種類型的燈光,用它們可以讓3D世界顯得真實 。
一、燈光類型
1、點光(Point Light)
從一個點向周圍均勻發射的光,有最大的照明範圍,亮度隨距離衰減,最明顯的一個例子就是我們家裡用的燈泡。
2、方向光(Directional Light)
方向光是一組沒有衰減的平行光,類似太陽光的效果。
3、聚光燈(Spot Light)
最複雜的一種燈,有光源點位置、有方向、有範圍、有發光的內徑和外徑,光照強度還會隨距離衰減。類似的例子是電筒。
二、燈光結構
D3D中燈光通過D3DLIGHT9結構來表示:
typedef struct D3DLIGHT9 {
D3DLIGHTTYPE Type;
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Ambient;
D3DVECTOR Position;
D3DVECTOR Direction;
float Range;
float Falloff;
float Attenuation0;
float Attenuation1;
float Attenuation2;
float Theta;
float Phi;
} D3DLIGHT9, *LPD3DLIGHT;
Type-燈光類型,共3種:D3DLIGHT_POINT、D3DLIGHT_SPOT、D3DLIGHT_DIRECTIONAL。
Diffuse-光源發出的漫反射光顏色。
Specular-光源發出的鏡面光顏色。
Ambient-光源發出的環境光顏色。
Position-用向量表示的光源世界坐標位置(對方向光無效)。
Direction-用向量表示的光源世界坐標照射方向(對點光源無效)。
Range-燈光能夠傳播的最大範圍(對方向光無效),該值不能應小於。
Falloff-燈光從內圓錐到外圓錐之間的強度衰減(僅對聚光燈有效),該值通常設為1.0f。
Attenuation0、Attenuation1、Attenuation2-燈光衰減變量,用來定義燈光強度的傳播距離衰減(對方向光無效)。
Attenuation0定義恆定衰減,
Attenuation1定義線性衰減,
Attenuation2定義二次衰減。
Attenuation0通常為0.0f,
Attenuation1通常為1.0f,
Attenuation2通常為0.0f。
適當的使用如下公式,D代表到光源的距離,A0、A1、A2分別與Attenuation0、Attenuation1、Attenuation2相匹配。
Theta-指定燈光內圓錐的角度(僅對聚光燈有效),單位是弧度。
Phi-指定外圓錐的角度(僅對聚光燈有效),單位是弧度。
三、燈光的設置
燈光的屬性設置好後,需要把這個燈光加入到場景中:
// 要讓渲染的時候燈光起作用,運行這條命令
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
// 設置0號燈為我們設置的燈
g_pd3dDevice->SetLight( 0, &light );
// 打開0號燈光
g_pd3dDevice->LightEnable( 0, TRUE );
在使用燈光的時候需要注意的一點是,要為每個頂點設定法線,只有設置了法線,燈光才會起作用。什麼是法線?其實就是一個和該點所在面垂直的向量。
