多媒體技術(shù)13DirectX編程入門_第1頁(yè)
多媒體技術(shù)13DirectX編程入門_第2頁(yè)
多媒體技術(shù)13DirectX編程入門_第3頁(yè)
多媒體技術(shù)13DirectX編程入門_第4頁(yè)
多媒體技術(shù)13DirectX編程入門_第5頁(yè)
已閱讀5頁(yè),還剩84頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

編號(hào):時(shí)間:2021年x月x日書山有路勤為徑,學(xué)海無(wú)涯苦作舟頁(yè)碼:第頁(yè)第13章DirectX編程入門DirectX是微軟公司為編寫游戲和其他高性能多媒體應(yīng)用程序而開發(fā)的一組高級(jí)的Windows低層API,它包含了對(duì)圖(圖形、視頻和三維動(dòng)畫)、聲音(聲效與音樂(lè))、輸入設(shè)備和網(wǎng)絡(luò)游戲等的支持。本章先概述DirectX的基本內(nèi)容,然后介紹DirectX的主要組件Direct3D和DirectSound的基本編程方法,并給出若干具體編程實(shí)例。13.1DirectX概述本節(jié)簡(jiǎn)單介紹DurectX的發(fā)展歷史、版本和功能的演化、結(jié)構(gòu)和模塊劃分。DurectX是Windows的一種多媒體API,它在保持設(shè)備無(wú)關(guān)性的同時(shí),可以讓應(yīng)用程序直接控制多媒體設(shè)備,從而能充分利用硬件的功能,因此可獲得最高的性能。DurectX自從推出以來(lái),就始終處在快速發(fā)展的過(guò)程之中。它已經(jīng)經(jīng)歷了多個(gè)版本,其模塊和功能也一直在不斷地增加和完善。DirectX是一種基于COM的系統(tǒng),主要由硬件抽象層HAL和硬件模擬層HEL所構(gòu)成。DurectX被分成若干個(gè)組件模塊,涵蓋了多媒體應(yīng)用的方方面面。而且這些組件的數(shù)目、名稱和功能,也是隨著其版本的演化而有所增減、改變和加強(qiáng)。13.1.1歷史微軟公司于1990年5月推出的Windows3.0大獲成功,它是一種與設(shè)備無(wú)關(guān)的具有圖形用戶界面(GUI)的操作系統(tǒng)。后來(lái)又于1992年3月推出Windows3.1,提供了對(duì)多媒體的支持。不過(guò)Windows的與設(shè)備無(wú)關(guān)的設(shè)計(jì)思想,雖然使得Windows向程序員提供了一個(gè)獨(dú)立于硬件的軟件開發(fā)優(yōu)秀平臺(tái),但它不讓應(yīng)用程序直接操作顯卡和聲卡等多媒體硬件,這樣就降低了多媒體應(yīng)用程序(特別是計(jì)算機(jī)游戲)的運(yùn)行效率,例如限制了動(dòng)畫的幀率、不提供混音功能等。所以當(dāng)時(shí)的Windows并不是一個(gè)可以開發(fā)和運(yùn)行高效多媒體程序(如3D游戲)的理想環(huán)境,逼迫PC游戲開發(fā)商只好繞開Windows而仍舊開發(fā)DOS下的游戲。為了改變這種難堪的局面,促使游戲界放棄DOS而使用Windows,微軟需要在設(shè)備無(wú)關(guān)性與高性能之間取得某種平衡,決定為Windows添加一種高性能的動(dòng)畫機(jī)制(以及后來(lái)的輸入與音響等),因此于1995年推出了GameSDK,后來(lái)改名為DirectX。其中的Direct指可以直接訪問(wèn)多媒體硬件;X指它的不同組成部分,如Direct3D、DirectSound、DirectInput和DirectPlay等。13.1.2版本與功能因?yàn)镈irectX必須支持多媒體設(shè)備的最新技術(shù)和功能,而多媒體硬件(尤其是顯卡[的3D性能])和技術(shù)始終處在高速發(fā)展過(guò)程中,所以DirectX的技術(shù)和版本也同樣在不斷地發(fā)展和演變,其中發(fā)展最快的是3D接口部分。下面列出DirectX的主要版本的發(fā)布時(shí)間、引入的新模塊和特性:1.0——1995年9月30日:DirectDraw、DirectSound、DirectInput、DirectPlay、DirectSetup;2.0——1996年6月5日:引入Direct3D(次版本有2.0a);3.0——1996年9月15日:支持MMX、為DirectSound補(bǔ)充DirectSound3DAPI(次版本有3.0a);4.0——無(wú)此版本號(hào);5.0——1997年7月16日:有許多改進(jìn),如受力反饋控制器、多顯示器支持、新的游戲控制面板、用戶界面的全面改進(jìn)等(次版本有5.1和5.2);6.0——1998年8月7日:添加新的3D特性(如添加DXUT框架)、支持AMD公司的3DNow!技術(shù)、性能較5.0有提高。在1999年2月3日推出的6.1版中,添加了DirectMusic模塊;7.0——1999年9月22日:改進(jìn)3D圖形和聲音、性能更快,為Direct3DAPI引入硬件傳送、光照和紋理壓縮、以及硬件加速,引入D3DX工具庫(kù)。使用Creative公司的EAX技術(shù)改進(jìn)3D聲音的算法(次版本有7.0a和7.1);8.0——2000年9月30日:將DirectDraw與Direct3D完全集成在一起、其中Direct3D的性能有了本質(zhì)上的飛躍(引入頂點(diǎn)/像素shader[著色引擎/光照模型]、支持硬件點(diǎn)精靈和三維體紋理),將DirectMusic與DirectSound更緊密地集成在一起構(gòu)成DirectXAudio,更新了DirectInput與DirectPlay,添加了DirectShow、拋棄了其余的DirectXMedia模塊。2001年11月11日推出的8.1版,被集成在WindowsXP中銷售,該版本添加了從DirectShow分離出的DMO(DirectXMediaObjects媒體對(duì)象)組件模塊。它還支持許多新的圖形特性,如像素著色引擎的1.2~1.4版、動(dòng)態(tài)/高分辨率紋理、新3D擴(kuò)展方法等(次版本有8.0a、8.1、8.1a和8.1b);9.0——2002年12月24日:添加許多新特性到DirectXGraphics和DirectShow中,例如將DirectDraw的功能并入到Direct3D之中,支持頂點(diǎn)和像素著色引擎的新版本2.0和3.0,引入裁剪測(cè)試、位移貼圖和多元紋理,支持128位浮點(diǎn)著色精度和根據(jù)顯示器自動(dòng)調(diào)整γ值等。也添加若干新特性到DirectInput、DirectPlay、DirectSound和DirectMusic中。(次版本有9.0a、9.0b和9.0c)。DirectX的最后一個(gè)以數(shù)字和字母命名的版本是2004年8月9日推出的9.0c,后來(lái)又于2004年10月、2005年的2/4/6/8/10月分別推出了它的多個(gè)升級(jí)版。從2005年12月推出的DirectX開始,其版本的命名發(fā)生了變化:主版本號(hào)改為DX,次版本改為發(fā)布的年月。一般是每?jī)蓚€(gè)月推出一個(gè)新版本,因此也叫做DirectX9.0c的雙月更新(bimonthlyupdates)。當(dāng)前最新版本為2006年10月11日推出的DXOctober2006。它們都包含了(于2002年推出的專為.NET框架設(shè)計(jì)的)托管(Managed)DirectX,將原來(lái)DirectX多個(gè)分離的COM模塊集成到了一個(gè)容易使用的單一CLR文件之中。10——?:DirectX不會(huì)有第10版了,因?yàn)槲④浌疽褜irectX的功能集成進(jìn)其新一代操作系統(tǒng)WindowsVista中,而不再將其作為一個(gè)額外的模塊了。但是會(huì)有Direct3D10,已于2006年12月13日隨Direct3DSDK的December2006版一起發(fā)布,并被嵌入到WindowsVista中。另外,作為學(xué)生和業(yè)余愛(ài)好者的DirectX替代產(chǎn)品,微軟公司于2004年3月24日宣布了用于托管運(yùn)行環(huán)境下計(jì)算機(jī)游戲的設(shè)計(jì)、開發(fā)和管理的框架和工具集XNA,并于2006年12月11日推出了XNAFrameworkRedistributable和XNAGameStudioExpress的1.0版,可用于Windows和Xbox360游戲的開發(fā)。WindowsAPI應(yīng)用程序WindowsAPI子系統(tǒng)(GDI、MMAPI、MCI、...)Windows驅(qū)動(dòng)程序接口DirectXWindowsAPI應(yīng)用程序WindowsAPI子系統(tǒng)(GDI、MMAPI、MCI、...)Windows驅(qū)動(dòng)程序接口DirectXHELHALPC硬件子系統(tǒng)DirectX圖13-1DirectX子系統(tǒng)DirectX是一種基于COM(ComponentObjectModel,組件對(duì)象模型)的系統(tǒng),它既不屬于驅(qū)動(dòng)程序?qū)樱膊粚儆趹?yīng)用層。DirectX的主要設(shè)計(jì)目標(biāo)是在提供某種設(shè)備獨(dú)立性的同時(shí)獲取高速度,為此微軟公司為DirectX設(shè)計(jì)了如圖13-1所示的體系結(jié)構(gòu)。其中:圖13-1DirectX子系統(tǒng)HAL=HardwareAbstractLayer(硬件抽象層)——負(fù)責(zé)檢測(cè)本機(jī)的硬件功能,并以一種獨(dú)立于設(shè)備的方式提供這些功能;HEL=HardwareEmulationLayer(硬件模擬層)——負(fù)責(zé)提供DirectX功能中本機(jī)硬件不支持部分的模擬實(shí)現(xiàn)。但是從8.0版起,DirectX就不再提供硬件模擬層HEL了,需要開發(fā)商、第三方或自己來(lái)編寫一個(gè)PSD(PluggableSoftwareDevice可插式軟件設(shè)備)連到DirectX提供的HEL接口上,稱之為參考設(shè)備。但是現(xiàn)在很少有這樣的PSD可用,因此新版本的DirectX是嚴(yán)重依賴于硬件的。13.1.4組成DirectX由多個(gè)(COM組件)模塊組成,而且隨著版本的演化,這些模塊也在不斷地增減、合并和改變。最新的DirectX組件的模塊構(gòu)成如圖13-2所示,括號(hào)中的數(shù)字為該模塊被首次引進(jìn)(或移出)的版本號(hào)。下面是DirectX的主要組成模塊的簡(jiǎn)單介紹:DirectXGraphics(圖形)——包括DirectDraw和Direct3D:DirectDraw(繪制)——二維圖形繪制(高速位圖傳送/視頻與2D動(dòng)畫)。從9.0版起,DirectDraw已被集成到了Direct3D之中。Direct3D(三維)——三維圖形繪制。分成保留(retained)和立即(immediate)兩種模式(mode):保留模式是一種高層API,建立在立即模式之上,使用起來(lái)方便容易,但是效率不高,適合于初學(xué)者;立即模式則是一種底層API,使用復(fù)雜,但是其效率比保留模式高得多。大多數(shù)DirectX應(yīng)用程序,特別是計(jì)算機(jī)游戲,都是采用立即模式進(jìn)行開發(fā)。自從6.0版以來(lái),保留模式API的發(fā)展停滯不前,而立即模式API的發(fā)展卻日新月異。不論是保留模式還是立即模式,Direct3D都是建立在DirectDraw之上的。從9.0版起,Direct3D包含了DirectDraw,它像OpenGL一樣也具有二維圖形繪制的功能。Direct3D的下一個(gè)版本為Durect3D10,為WindowsVista的一個(gè)有機(jī)組成部分。D3DX(Direct3D擴(kuò)展)——為Direct3D服務(wù)的實(shí)用工具庫(kù),執(zhí)行公共的數(shù)學(xué)計(jì)算和一些復(fù)雜的任務(wù),包含若干簡(jiǎn)化3D模型使用的類,如粒子系統(tǒng)(particlesystem)。D3DX由動(dòng)態(tài)鏈接庫(kù)(DLL)提供。DXUT(編程框架)——建立在Direct3DAPI之上的樣例框架,也叫通用文件框架,可以幫助程序員減少在繁瑣的平凡工作(如創(chuàng)建窗口、創(chuàng)建設(shè)備、處理Windows消息和設(shè)備事件等)上所花的時(shí)間。DirectXDirectXDirectXGraphics(8.0)DirectDraw(1.0)Direct3D(2.0)DirectXAudio(8.0)DirectSound(1.0)DirectMusic(6.1)DirectSound3D(3.0)DirectInput(1.0)DirectPlay(1.0)DirectSetup(1.0)DirectXMedia(5.0)DirectShow(5.0)DirectAnimation(5.0)DirectX視頻加速(5.0)Direct3D保留模式(5.0)DirectXTransform(5.0)并入(9.0)移入平臺(tái)SDK(9.0c2005.4)建議用WinSocket和WinFirewallAPI代替(9.0c)并入(8.0)移入WindowsMediaSDK(8.0)XInput(9.0c2005.10)XboxLive(Vista)MediaFoundation(Vista)XACT(9.0c2006.2)XNA(Xbox/Vista)DirectXMediaObjects(8.1)分出(8.1)并入(6.0)Direct3D立即模式(2.0)D3DX(7.0)/DXUT(6.0)圖13-2DirectX的組成模塊DirectXAudio(音頻)——包括DirectSound和DirectMusic:DirectSound(聲音)——主要針對(duì)波形音頻,底層接口??捎糜陂_發(fā)播放和捕捉波形音頻的高性能立體與三維(DirectSound3D)音頻應(yīng)用程序。在下一代DirectX中,DirectSound的功能將由XACT(MicrosoftCross-PlatformAudioCreationTool微軟跨平臺(tái)音頻生成工具)來(lái)代替。DirectMusic(音樂(lè))——主要針對(duì)MIDI音樂(lè),高層接口。為基于波形、MIDI聲音或DirectMusic生成器所創(chuàng)造的動(dòng)態(tài)內(nèi)容之音樂(lè)和非音樂(lè)聲道提供一個(gè)完整的解決方案。XACT(游戲音頻)——XACT(MicrosoftCross-PlatformAudioCreationTool,微軟跨平臺(tái)音頻生成工具),是一種多人合作的音頻設(shè)計(jì)工具和相關(guān)API,用于游戲的動(dòng)態(tài)音頻開發(fā)。DirectInput(輸入)——提供對(duì)各種輸入設(shè)備的支持,包括對(duì)受力反饋(force-feedback)技術(shù)的全面支持。在下一代DirectX中,DirectInput將被XInput代替。DirectPlay(游戲)——提供對(duì)多人網(wǎng)絡(luò)游戲的支持。在最新的DirectX版本中,微軟公司反對(duì)(deprecate)使用DirectPlay,而建議改用WindowsSockets和WindowsFirewallAPI來(lái)代替。在下一代DirectX中,DirectPlay可能會(huì)被XboxLive代替。DirectSetup(安裝)——提供DirectX組件的一次性調(diào)用安裝的一個(gè)簡(jiǎn)單API(自動(dòng)安裝DirectX驅(qū)動(dòng)程序)。DirectShow(展示)——提供多媒體(音視頻)流的高質(zhì)量捕捉和重放。在8.0版之前,DirectShow是DirectXMedia的一個(gè)組成模塊。到8.0版時(shí),因?yàn)镈irectXSDK拋棄了DirectXMedia,所以才將DirectShow集成到了DirectX之中。在DirectX9.0c的2005年4月升級(jí)版中,DirectShow又被移出DirectX,放入微軟公司的平臺(tái)SDK之中。DirectXMediaObjects(媒體對(duì)象DMO)——基于COM的多媒體和數(shù)據(jù)流組件,支持音視頻的編解碼器和特效。是在DirectX的8.1版時(shí),從DirectShow分出的,其功能類似于DirectShow的過(guò)濾器。DirectXMedia(媒體)——是一個(gè)用于流媒體應(yīng)用的外部API集合。在DirectX6.0之前,DirectXMediaSDK和DirectXSDK是兩個(gè)分離的SDK。在6.0版時(shí)DirectXMediaSDK被集成到DirectXSDK之中。DirectXMedia的運(yùn)行模塊,被集成到Windows和IE之中。到了8.0版時(shí),DirectXMedia又被DirectXSDK拋棄(其核心模塊DirectShow被集成到了DirectX之中),其功能被隨Windows2000Server推出的WindowsMediaSDK所代替。DirectXTransform(變換)——用于產(chǎn)生二、三維圖形的各種效果,如α混色和表面彎曲等。DirectAnimation(動(dòng)畫)——集成多種媒體類型來(lái)創(chuàng)建復(fù)雜動(dòng)畫,并可用作網(wǎng)頁(yè)內(nèi)容。DirectXVideoAcceleration(視頻加速DXVA)——利用硬件加速二維視頻的解碼操作。Direct3DRetainedMode(保留模式)——Direct3D的保留模式是一種高層API,建立在Direct3D立即模式之上,使用起來(lái)方便容易,但是效率不高,適合于初學(xué)者。DirectShow(展示)——支持音視頻流的高質(zhì)量采集和重放。13.1.5編程準(zhǔn)備為了用VC編寫DirectX應(yīng)用程序,必須先下載并安裝DirectXSDK,并進(jìn)行必要的頭/庫(kù)文件路徑和鏈接庫(kù)的設(shè)置。下面以WindowsXP中文版環(huán)境下的VisualC++2005中文版和DirectX9.0cAugust2006SDK為例,介紹進(jìn)行具體的DirectX編程之前,所需做的必要準(zhǔn)備工作。下載并安裝DirectXSDK可以從微軟公司的官方網(wǎng)站(/windows/directx/)下載最新的DirectXSDK,如dxsdk_dec2006.exe(448MB)。安裝完成后,會(huì)在安裝目錄(缺省為“C:\ProgramFiles\MicrosoftDirectXSDK((December2006)”)中生成DeveloperRuntime、Documentation、Include、Lib、Redist、Samples和Utilities等多個(gè)子目錄。安裝時(shí)還會(huì)為Windows操作系統(tǒng)生成名為“MicrosoftDirectXSDK((December2006)”的程序組,包含多個(gè)子程序組和程序。安裝程序會(huì)將DirectXSDK的幫助文檔,也安裝到VisualStudio2005的幫助系統(tǒng)內(nèi),位于其“目錄/DirectXSDK((December2006)”目錄之中,包含“DirectXSDK((December2006)C++”和“DirectXSDK((December2006)Managed”兩個(gè)幫助子目錄。設(shè)置包含和庫(kù)路徑在VisualStudio2005中文版的IDE中,選“工具/選項(xiàng)”菜單項(xiàng),打開“選項(xiàng)”對(duì)話框(參見(jiàn)圖13-5)。圖13-5VisualStudio2005的“選項(xiàng)”對(duì)話框再選該對(duì)話框左邊的“項(xiàng)目和解決方案/VC++目錄”路徑,在右邊的“顯示以下內(nèi)容的目錄”欄的下拉式列表框中,選“包含文件”項(xiàng)。按該欄下面的“新行”鈕,則在其下方的顯示欄中會(huì)出現(xiàn)新行,再按新行右端的帶省略號(hào)的瀏覽鈕,在彈出的“選擇目錄”對(duì)話框中,選擇DirectXSDK的Include目錄所在的路徑“C:\ProgramFiles\MicrosoftDirectXSDK(August2006)\Include”,然后按“打開”關(guān)閉“選擇目錄”對(duì)話框。結(jié)果參見(jiàn)圖13-6。圖13-6設(shè)置DirectX的“包含文件”的路徑可類似選擇“庫(kù)文件”項(xiàng),添加庫(kù)文件路徑“C:\ProgramFiles\MicrosoftDirectXSDK(August2006)\Lib\x86”,結(jié)果參見(jiàn)圖13-7。最后,按“確定”鈕,關(guān)閉“選項(xiàng)”對(duì)話框。圖13-7設(shè)置DirectX的“庫(kù)文件”的路徑注意,對(duì)DirectX的包含路徑和庫(kù)路徑的設(shè)置,對(duì)所有項(xiàng)目都有效。設(shè)置鏈接庫(kù)先創(chuàng)建一個(gè)DirectX應(yīng)用程序的MFC單文檔項(xiàng)目(如DxTest),再在VS05的IDE中,選“項(xiàng)目/屬性”,打開“DxTest屬性頁(yè)”對(duì)話框。在左上角的“配置”欄中,選中“所有配置”項(xiàng);再選左邊的路徑“配置屬性/鏈接器/輸入”,在右邊的“附加依賴項(xiàng)”欄中,添加d3d9.libd3dx9.libd3dxof.libdsound.libdxguid.libwinmm.lib等鏈接庫(kù)(在多個(gè)庫(kù)文件之間,用空格分隔)。具體添加哪些DirectX庫(kù),與具體應(yīng)用程序所使用的DirectX模塊有關(guān),你也可以查看DirectX的庫(kù)目錄。最后,按“應(yīng)用”鈕和“確定”鈕,關(guān)閉屬性頁(yè)對(duì)話框。參見(jiàn)圖13-8。圖13-8設(shè)置DirectX的鏈接庫(kù)注意,對(duì)DirectX鏈接庫(kù)的設(shè)置,只對(duì)VC05中當(dāng)前打開的單個(gè)項(xiàng)目有效。在安裝了DirectXSDK,并設(shè)置好文件路徑和鏈接庫(kù)后,就可以開始編寫具體的DirectX應(yīng)用程序了。DirectX的組件眾多、功能強(qiáng)大、編程復(fù)雜,完整的介紹需要幾本大部頭的專著才行,本書只準(zhǔn)備簡(jiǎn)單介紹DirectX的最主要模塊——Direct3D和DirectSound編程的最基本內(nèi)容。13.2Direct3D編程簡(jiǎn)介Direct3D(直接三維)是DirectX的核心模塊,新版本的Direct3D中還包含原來(lái)DirectDraw模塊的2D功能。因此,現(xiàn)在的Direct3D是DirectXGraphics的唯一模塊,具有DirectX(二、三維)圖形的全部功能。13.2.1流水線與設(shè)備Direct3D用圖形流水線(graphicspipeline)來(lái)處理和渲染場(chǎng)景(renderscene),而Direct3D設(shè)備(device)是執(zhí)行變換(transformation)和光照(lighting)等操作的渲染部件。Direct3D圖形流水線可通過(guò)Direct3D圖形流水線來(lái)充分利用硬件性能,以提供高效處理和繪制Direct3D場(chǎng)景到顯示器的能力。圖13-9為流水線(pipeline,管線/管道/流程)的組成模塊框圖。頂點(diǎn)數(shù)據(jù)頂點(diǎn)數(shù)據(jù)圖元數(shù)據(jù)鑲嵌頂點(diǎn)處理幾何處理像素處理像素繪制紋理采樣器紋理表面圖13-9Direct3D圖形流水線Direct3D設(shè)備圖13-10Direct3D設(shè)備架構(gòu)變換模塊光照模塊光柵化器Direct3D設(shè)備架構(gòu)Direct3D設(shè)備(device)是Direct3D的渲染部件,它封裝和存儲(chǔ)渲染狀態(tài)。另外,它還執(zhí)行變換和光照等操作,并且光柵化圖像到表面(如屏幕)。在結(jié)構(gòu)上,Direct3D設(shè)備包含變換模塊(transformationmodule)、光照模塊(lightingmodule)和光柵化器(rasteriz圖13-10Direct3D設(shè)備架構(gòu)變換模塊光照模塊光柵化器Direct3D設(shè)備架構(gòu)當(dāng)前,Direct3D有兩種主要的設(shè)備類型:HAL設(shè)備(haldevice)——具有硬件加速的光柵化(rasterization),可同時(shí)使用硬件和軟件的頂點(diǎn)處理進(jìn)行著色(shading)。參考設(shè)備(referencedevice)——由軟件驅(qū)動(dòng)程序提供,現(xiàn)在主要用于性能測(cè)試。創(chuàng)建Direct3D對(duì)象創(chuàng)建Direct3D設(shè)備對(duì)象創(chuàng)建Direct3D對(duì)象創(chuàng)建Direct3D設(shè)備對(duì)象設(shè)置渲染狀態(tài)定義頂點(diǎn)格式創(chuàng)建頂點(diǎn)緩沖區(qū)鎖定頂點(diǎn)緩沖區(qū)解鎖頂點(diǎn)緩沖區(qū)開始場(chǎng)景結(jié)束場(chǎng)景構(gòu)造幾何對(duì)象設(shè)置材質(zhì)和光照或紋理設(shè)置設(shè)備的流源和頂點(diǎn)格式繪制圖元展現(xiàn)場(chǎng)景進(jìn)行世界、觀察和投影矩陣變換清除對(duì)象清除顯示表面13.2.2基本編程過(guò)程Direct3D的基本編程過(guò)程如圖13-11所示。下面各小節(jié)依次介紹Direct3D編程的基本步驟和方法。13.2.3創(chuàng)建和初始化對(duì)象為了使用Direct3D,你必須首先創(chuàng)建一個(gè)應(yīng)用窗口,然后再創(chuàng)建和初始化Direct3D對(duì)象。利用這些對(duì)象所實(shí)現(xiàn)的COM接口來(lái)操作它們,以創(chuàng)建繪制場(chǎng)景所需的其它對(duì)象。如果進(jìn)行MFC編程,則可以省略創(chuàng)建窗口這一步,而直接使用視圖類所代表的客戶區(qū)窗口。圖13-11Direct3D編程的基本過(guò)程下面介紹的是初始化Direct3D的內(nèi)容,包括創(chuàng)建Direct3D對(duì)象、創(chuàng)建Direct3D圖13-11Direct3D編程的基本過(guò)程創(chuàng)建Direct3D對(duì)象可使用全局函數(shù)Direct3DCreate9來(lái)創(chuàng)建Direct3D接口對(duì)象:IDirect3D9*Direct3DCreate9(//成功返回指向IDirect3D9接口的指針,失敗返回NULLUINTSDKVersion//必須為D3D_SDK_VERSION);例如:IDirect3D9*g_pD3D=Direct3DCreate9(D3D_SDK_VERSION);創(chuàng)建Direct3D設(shè)備可使用IDirect3D9接口的CreateDevice方法來(lái)創(chuàng)建設(shè)備(尾參數(shù)的返回值):HRESULTCreateDevice(//成功返回D3D_OK(=0)UINTAdapter,//顯卡(displayadapter)序號(hào),D3DADAPTER_DEFAULT為主顯卡D3DDEVTYPEDeviceType,//設(shè)備的枚舉類型,一般取為D3DDEVTYPE_HALHWNDhFocusWindow,//焦點(diǎn)窗口句柄,可取為this->m_hWndDWORDBehaviorFlags,//控制設(shè)備的創(chuàng)建行為之選項(xiàng)組合,可以采用硬件或軟件//的頂點(diǎn)處理,如D3DCREATE_SOFTWARE_VERTEXPROCESSINGD3DPRESENT_PARAMETERS*pPresentationParameters,//指向展現(xiàn)參數(shù)結(jié)構(gòu)//D3DPRESENT_PARAMETERS的指針I(yè)Direct3DDevice9**ppReturnedDeviceInterface//代表被創(chuàng)建設(shè)備的//IDirect3DDevice9返回接口的指針地址);其中,展現(xiàn)參數(shù)結(jié)構(gòu)D3DPRESENT_PARAMETERS的定義為:typedefstructD3DPRESENT_PARAMETERS{//展現(xiàn)參數(shù)結(jié)構(gòu)UINTBackBufferWidth,BackBufferHeight;//后臺(tái)緩沖區(qū)的寬高(以像素為單位),//對(duì)窗口模式可取為0,對(duì)全屏模式則必須與當(dāng)前顯卡枚舉模式的一致D3DFORMATBackBufferFormat;//后臺(tái)緩沖區(qū)的格式,可取為//D3DFMT_UNKNOWN(=0)UINTBackBufferCount;//后臺(tái)緩沖區(qū)計(jì)數(shù),可取為0~3,取0時(shí)等價(jià)于1D3DMULTISAMPLE_TYPEMultiSampleType;//多樣本類型,一般取為 //D3DMULTISAMPLE_NONE(=0)DWORDMultiSampleQuality;//多樣本質(zhì)量水平,一般取0D3DSWAPEFFECTSwapEffect;//交換效果,可取為 //D3DSWAPEFFECT_DISCARD(=1)、D3DSWAPEFFECT_FLIP(=2) //和D3DSWAPEFFECT_COPY(=3)等枚舉值HWNDhDeviceWindow;//設(shè)備窗口的句柄,對(duì)窗口模式可取為NULL(=0)BOOLWindowed;//應(yīng)用程序在窗口/全屏中運(yùn)行時(shí)取TRUE/FALSEBOOLEnableAutoDepthStencil;//允許自動(dòng)深度模板,為TRUE則由Direct3D//來(lái)管理應(yīng)用程序的深度緩沖區(qū)D3DFORMATAutoDepthStencilFormat;//自動(dòng)深度模板格式,可取//D3DFMT_D16、D3DFMT_D24S8和D3DFMT_D32等枚舉值DWORDFlags;//表現(xiàn)標(biāo)志D3DPRESENTFLAG常數(shù)之一,可取為0UINTFullScreen_RefreshRateInHz;//全屏?xí)r的屏幕刷新率,對(duì)窗口模式必須為0UINTPresentationInterval;//前后臺(tái)緩沖區(qū)交換的最大速率,可取為//D3DPRESENT_INTERVAL_DEFAULT(=0)}D3DPRESENT_PARAMETERS;例如://設(shè)置創(chuàng)建D3D設(shè)備用的表現(xiàn)結(jié)構(gòu)D3DPRESENT_PARAMETERSd3dpp;//定義表現(xiàn)結(jié)構(gòu)變量ZeroMemory(&d3dpp,sizeof(d3dpp));//內(nèi)存清零d3dpp.Windowed=TRUE;//窗口模式d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;//放棄交換效果d3dpp.BackBufferFormat=D3DFMT_UNKNOWN;//未知格式d3dpp.EnableAutoDepthStencil=TRUE;//允許自動(dòng)深度模板d3dpp.AutoDepthStencilFormat=D3DFMT_D16;//16位深度緩沖LPDIRECT3DDEVICE9g_pd3dDevice;//定義D3D設(shè)備接口的指針//創(chuàng)建D3D設(shè)備對(duì)象(獲取D3D設(shè)備接口的指針)g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, this->m_hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,&g_pd3dDevice);設(shè)置設(shè)備的渲染狀態(tài)利用IDirect3D9接口的CreateDevice方法所返回的設(shè)備接口IDirect3DDevice9的指針,可以調(diào)用該接口的設(shè)置渲染(render著色)狀態(tài)方法SetRenderState,來(lái)初始化設(shè)備:HRESULTSetRenderState(//成功返回D3D_OK(=0)D3DRENDERSTATETYPEState,//設(shè)備狀態(tài)DWORDValue//設(shè)置值);其中,設(shè)備狀態(tài)State,可取D3DRENDERSTATETYPE枚舉的任意值,如D3DRS_ZENABLE(允許Z緩沖)、D3DRS_FILLMODE(填充模式)、D3DRS_SHADEMODE(陰影模式)、D3DRS_ALPHATESTENABLE(允許α測(cè)試)、D3DRS_CULLMODE(剔除模式)、D3DRS_FOGENABLE(允許霧化)、D3DRS_LIGHTING(光照)、D3DRS_DITHERENABLE(允許抖動(dòng))、……。例如:g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);//關(guān)閉背面剔除g_pd3dDevice->SetRenderState(D3DRS_ZENABLE,TRUE);//允許Z緩沖g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);//關(guān)閉光照13.2.4創(chuàng)建場(chǎng)景三維場(chǎng)景是由若干物體(幾何對(duì)象)構(gòu)成的,復(fù)雜的幾何對(duì)象由多個(gè)簡(jiǎn)單的圖元(點(diǎn)、線、三角形和多邊形等)所組成,而圖元(primitive)又是頂點(diǎn)(vertex)的集合。圖13-123D圖元表面的三角網(wǎng)格3D圖元一般是一個(gè)多面體,通常用其表面的三角網(wǎng)格來(lái)表示,參見(jiàn)圖13-12。所以最基本的圖元是三角形和頂點(diǎn)。圖13-123D圖元表面的三角網(wǎng)格創(chuàng)建場(chǎng)景中的幾何對(duì)象,等價(jià)于建立表示該幾何體的頂點(diǎn)集合。因此,必須先定義自己的頂點(diǎn)結(jié)構(gòu)并創(chuàng)建頂點(diǎn)緩沖區(qū),然后在鎖定頂點(diǎn)緩沖區(qū)后,再通過(guò)給頂點(diǎn)緩沖區(qū)中的各頂點(diǎn)結(jié)構(gòu)賦值來(lái)構(gòu)造幾何對(duì)象,最后解鎖頂點(diǎn)緩沖區(qū)。定義頂點(diǎn)結(jié)構(gòu)Direct3D使用一種FVF(FlexibleVertexFormat可變頂點(diǎn)格式)結(jié)構(gòu)來(lái)定義頂點(diǎn),以滿足用戶的不同需要。在FVF結(jié)構(gòu)CUSTOMVERTEX中,可以包含描述頂點(diǎn)的位置、RHW(reciprocalhomogeneousw倒數(shù)齊次w,表示已變換頂點(diǎn)位置的齊次坐標(biāo)w分量)、法向、大小和(漫射、鏡面反射)顏色等字段,具體內(nèi)容由用戶根據(jù)需要自己來(lái)確定,但是各字段之間的相對(duì)順序不能改變。其中,頂點(diǎn)的位置和法向等字段,一般為三維點(diǎn)向量,可以用Direct3D的擴(kuò)展三維向量結(jié)構(gòu)D3DXVECTOR3來(lái)表示:typedefstructD3DXVECTOR3{FLOATx;FLOATy;FLOATz;}D3DXVECTOR3;其中的FLOAT為float的typedef類型,定義在windef.h頭文件中。而顏色一般采用DWORD的typedef定義類型D3DCOLOR。例如: structCUSTOMVERTEX{//含位置、法向量和顏色的自定義頂點(diǎn)結(jié)構(gòu) D3DXVECTOR3position;//未變換頂點(diǎn)的3D位置 D3DXVECTOR3normal;//頂點(diǎn)的表面法向量 D3DCOLORcolor;//顏色 };或:structCUSTOMVERTEX{//含位置、顏色和紋理坐標(biāo)的自定義頂點(diǎn)結(jié)構(gòu)D3DXVECTOR3position;//未變換頂點(diǎn)的3D位置D3DCOLORcolor;//顏色FLOATtu,tv;//紋理坐標(biāo)};或:structCUSTOMVERTEX{//含位置齊次坐標(biāo)和顏色的自定義頂點(diǎn)結(jié)構(gòu) FLOATx,y,z,rhw;//已變換頂點(diǎn)的3D位置 DWORDcolor;//顏色 };用戶在定義了自己的頂點(diǎn)結(jié)構(gòu)類型后,還需要定義一個(gè)對(duì)應(yīng)的(宏)常量,來(lái)描述該結(jié)構(gòu)的字段內(nèi)容。該(宏)常量由若干表示頂點(diǎn)格式的標(biāo)志位符號(hào)常量(參見(jiàn)表13-1)的位或組合而成。表13-1頂點(diǎn)數(shù)據(jù)格式標(biāo)志符號(hào)常量值數(shù)據(jù)類型描述D3DFVF_XYZ0x002float,float,float未轉(zhuǎn)換的頂點(diǎn)坐標(biāo)D3DFVF_XYZRHW0x004float,float,float,float已轉(zhuǎn)換的頂點(diǎn)坐標(biāo)D3DFVF_XYZB1~50x006/8/a/c/e1-3個(gè)float含權(quán)重i的頂點(diǎn)坐標(biāo)D3DFVF_XYZW0x4002float,float,float,float已轉(zhuǎn)換和裁剪的頂點(diǎn)坐標(biāo)D3DFVF_NORMAL0x010float,float,float頂點(diǎn)的法線D3DFVF_PSIZE0x020float點(diǎn)大小D3DFVF_DIFFUSE0x040DWORD(ARGB)漫射顏色D3DFVF_SPECULAR0x080DWORD(ARGB)鏡面反射顏色D3DFVF_TEX0~80x0~8001-4個(gè)floati重紋理映射例如:#defineD3DFVF_CUSTOMVERTEX(D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE)或:#defineD3DFVF_CUSTOMVERTEX(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)或:constDWORDFVF=(D3DFVF_XYZRHW|D3DFVF_DIFFUSE);創(chuàng)建頂點(diǎn)緩沖區(qū)在定義了頂點(diǎn)結(jié)構(gòu)后,就可以創(chuàng)建頂點(diǎn)緩沖區(qū)了,這可以由IDirect3DDevice9接口的CreateVertexBuffer方法來(lái)完成:HRESULTCreateVertexBuffer(//成功返回D3D_OK(=0)UINTLength,//緩沖區(qū)的字節(jié)大小,一般為n*sizeof(CUSTOMVERTEX)DWORDUsage,//緩沖區(qū)用法的附加屬性標(biāo)志,一般為0DWORDFVF,//頂點(diǎn)結(jié)構(gòu)格式常量D3DPOOLPool,//緩沖區(qū)所在的內(nèi)存池類型(D3DPOOL枚舉值)IDirect3DVertexBuffer9**ppVertexBuffer,//返回被創(chuàng)建的頂點(diǎn)緩沖區(qū)指針HANDLE*pSharedHandle//保留,設(shè)為NULL);其中,內(nèi)存池類型D3DPOOL枚舉的定義為:typedefenumD3DPOOL{//內(nèi)存池類型枚舉D3DPOOL_DEFAULT=0,//AGP存儲(chǔ)器或顯存D3DPOOL_MANAGED=1,//AGP存儲(chǔ)器或顯存,且在系統(tǒng)內(nèi)存中還有一份拷貝D3DPOOL_SYSTEMMEM=2,//系統(tǒng)內(nèi)存D3DPOOL_SCRATCH=3,//系統(tǒng)內(nèi)存中的臨時(shí)池D3DPOOL_FORCE_DWORD=0x7fffffff//未使用(強(qiáng)制該枚舉被編譯成32位)}D3DPOOL;例如:g_pd3dDevice->CreateVertexBuffer(100*sizeof(CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&g_pVB,NULL);或: g_pd3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),0,FVF,D3DPOOL_MANAGED,&g_pVB,NULL);構(gòu)造點(diǎn)集創(chuàng)建三維場(chǎng)景中的幾何對(duì)象,需要計(jì)算和構(gòu)造描述該幾何對(duì)象的點(diǎn)集。具體做法是:先定義一個(gè)頂點(diǎn)指針(用于操作頂點(diǎn)數(shù)組);再調(diào)用Lock方法來(lái)獲取頂點(diǎn)緩沖區(qū)的首地址(賦值給頂點(diǎn)指針),并鎖定該區(qū)域僅供當(dāng)前操作使用;然后利用該頂點(diǎn)指針,將計(jì)算的頂點(diǎn)結(jié)構(gòu)值填入頂點(diǎn)緩沖區(qū),從而構(gòu)造出幾何對(duì)象;最后調(diào)用Unlock方法解鎖頂點(diǎn)緩沖區(qū)。IDirect3DVertexBuffer9接口的Lock和Unlock方法的定義為:HRESULTLock(//成功返回D3D_OK(=0)UINTOffsetToLock,//鎖定的偏移地址UINTSizeToLock,//鎖定的字節(jié)數(shù)VOID**ppbData,//返回被鎖定的緩沖區(qū)頭的指針DWORDFlags//鎖定方式標(biāo)志,可為0或下列符號(hào)常量的組合: //D3DLOCK_DISCARD、D3DLOCK_NO_DIRTY_UPDATE、//D3DLOCK_NOSYSLOCK、D3DLOCK_READONLY、//D3DLOCK_NOOVERWRITE);HRESULTUnlock();//成功返回D3D_OK(=0)例如:CUSTOMVERTEX*pVertices;g_pVB->Lock(0,0,(void**)&pVertices,0);……//給頂點(diǎn)緩沖區(qū)中的各頂點(diǎn)結(jié)構(gòu)賦值(構(gòu)造幾何對(duì)象的點(diǎn)集)g_pVB->Unlock();13.2.5矩陣變換描述單個(gè)物體(3D幾何對(duì)象)一般采用的是本地相對(duì)坐標(biāo)。因此,在渲染之前,需要將它們都轉(zhuǎn)換為描述場(chǎng)景的統(tǒng)一世界空間(worldspace)坐標(biāo),這對(duì)應(yīng)于世界矩陣變換。為了將三維場(chǎng)景顯示在二維屏幕上,還需要選擇一個(gè)觀察點(diǎn)(眼睛/攝像機(jī))和觀察角度(方向/坐標(biāo))(對(duì)應(yīng)于觀察坐標(biāo)矩陣變換),并將3D場(chǎng)景投影到一個(gè)2D平面(屏幕)上(對(duì)應(yīng)于投影矩陣變換),還要將超出屏幕的部分去掉(裁剪),也可以將場(chǎng)景投射到屏幕的某個(gè)矩形區(qū)域中(視口縮放)。參見(jiàn)圖13-13。世界世界變換觀察變換投影變換裁剪與視口縮放頂點(diǎn)光柵器變換引擎圖13-13Direct3D的變換引擎下面依次對(duì)這些變換加以介紹,這需要首先介紹Direct3D中的矩陣定義和變換方法。矩陣與變換在Direct3D中,定義了矩陣(matrix)結(jié)構(gòu)D3DXMATRIX:typedefstructD3DXMATRIX{//矩陣結(jié)構(gòu)struct{//注意,C/C++的變量名可以下劃線開頭(但不能以數(shù)字開頭)FLOAT_11;FLOAT_12;FLOAT_13;FLOAT_14;FLOAT_21;FLOAT_22;FLOAT_23;FLOAT_24;FLOAT_31;FLOAT_32;FLOAT_33;FLOAT_34;FLOAT_41;FLOAT_42;FLOAT_43;FLOAT_44;};}D3DXMATRIX;對(duì)應(yīng)于4*4的浮點(diǎn)矩陣:在Direct3D中,還定義了一個(gè)對(duì)IntelP4CPU運(yùn)算進(jìn)行了優(yōu)化的16字節(jié)對(duì)齊的矩陣結(jié)構(gòu)(從D3DXMATRIX派生的C++結(jié)構(gòu)對(duì)象):typedefstruct_D3DXMATRIXA16:publicD3DXMATRIX{//16字節(jié)對(duì)齊矩陣結(jié)構(gòu)_D3DXMATRIXA16();_D3DXMATRIXA16(CONSTFLOAT*f);_D3DXMATRIXA16(CONSTD3DMATRIX&m);_D3DXMATRIXA16(FLOAT_11,FLOAT_12,FLOAT_13,FLOAT_14,FLOAT_21,FLOAT_22,FLOAT_23,FLOAT_24,FLOAT_31,FLOAT_32,FLOAT_33,FLOAT_34,FLOAT_41,FLOAT_42,FLOAT_43,FLOAT_44);void*operatornew(size_ts);void*operatornew[](size_ts);voidoperatordelete(void*p);voidoperatordelete[](void*p);struct_D3DXMATRIXA16&operator=(CONSTD3DXMATRIX&rhs);}_D3DXMATRIXA16;typedefD3DX_ALIGN16_D3DXMATRIXA16D3DXMATRIXA16;Direct3D還提供了若干全局矩陣函數(shù),如:D3DXMATRIX*D3DXMatrixIdentity(D3DXMATRIX*pOut);//創(chuàng)建單位矩陣FLOATD3DXMatrixDeterminant(CONSTD3DXMATRIX*pM);//返回矩陣的行列式值D3DXMATRIX*D3DXMatrixInverse(//計(jì)算逆矩陣D3DXMATRIX*pOut,//結(jié)果矩陣FLOAT*pDeterminant,//行列式值,可置為NULLCONSTD3DXMATRIX*pM//原矩陣);D3DXMATRIX*D3DXMatrixMultiply(//兩矩陣相乘D3DXMATRIX*pOut,//結(jié)果矩陣CONSTD3DXMATRIX*pM1,//矩陣1CONSTD3DXMATRIX*pM2//矩陣2);矩陣變換(transform)的實(shí)施,可采用IDirect3DDevice9接口提供的SetTransform方法:HRESULTSetTransform(//成功返回D3D_OK(=0)D3DTRANSFORMSTATETYPEState,//變換類型狀態(tài)值CONSTD3DMATRIX*pMatrix//變換矩陣);其中State的取值可為D3DTRANSFORMSTATETYPE枚舉類型或D3DTS_WORLDMATRIX宏的值。如:D3DTS_VIEW(=2,觀察變換)、D3DTS_PROJECTION(=3,投影變換)、D3DTS_TEXTURE0~7(=16~23,紋理變換)、D3DTS_WORLD(=256,世界變換)等。例如:D3DXMATRIXA16matWorld;//定義矩陣結(jié)構(gòu)對(duì)象D3DXMatrixIdentity(&matWorld);//變成單位矩陣……//對(duì)matWorld進(jìn)行其他矩陣變換g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);//實(shí)施變換世界變換圖13-14世界變換一般用每個(gè)物體各自的本地坐標(biāo)來(lái)描述所對(duì)應(yīng)的3D幾何對(duì)象,而用統(tǒng)一的世界坐標(biāo)來(lái)描述整個(gè)場(chǎng)景(參見(jiàn)圖13-14),渲染之前需要將頂點(diǎn)從本地坐標(biāo)系轉(zhuǎn)換到世界坐標(biāo)系。稱這種從本地坐標(biāo)到世界坐標(biāo)的轉(zhuǎn)換為世界變換(worldtransform),世界變換包含平移(translation)、旋轉(zhuǎn)(rotation)和縮放(scaling)等三種具體變換類型,它們都可用對(duì)應(yīng)的矩陣變換來(lái)表示。圖13-14世界變換下面是Direct3D提供的若干世界矩陣變換的全局函數(shù):D3DXMATRIX*D3DXMatrixTranslation(//平移變換D3DXMATRIX*pOut,//原/結(jié)果矩陣FLOATx,//x偏移量FLOATy,//y偏移量FLOATz//z偏移量);D3DXMATRIX*D3DXMatrixRotationX[Y/Z](//(繞x[y/z]軸的)旋轉(zhuǎn)變換D3DXMATRIX*pOut,//原/結(jié)果矩陣FLOATAngle//旋轉(zhuǎn)角度(弧度單位));D3DXMATRIX*D3DXMatrixScaling(//縮放變換D3DXMATRIX*pOut,//原/結(jié)果矩陣FLOATsx,//x方向的比例因子FLOATsy,//y方向的比例因子FLOATsz//z方向的比例因子);可以通過(guò)這些函數(shù),獲得所需要的各種變換矩陣。最后,還須使用D3DTS_WORLD狀態(tài)值,來(lái)調(diào)用IDirect3DDevice9接口的SetTransform方法,以實(shí)施最終矩陣所對(duì)應(yīng)的世界變換。例如:D3DXMatrixTranslation(&matWorld,m_xPos,m_yPos,m_zPos);//平移D3DXMatrixRotationX(&matWorld,m_fPitch);//繞x軸旋轉(zhuǎn)g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);//實(shí)施世界變換觀察變換觀察變換(viewtransform),可在世界坐標(biāo)系(xw,yw,zw)中設(shè)置和改變觀察者的位置和方向,將世界空間中的頂點(diǎn)轉(zhuǎn)換到攝影空間(cameraspace)(xe,ye,ze),參見(jiàn)圖13-15。圖13-15觀察變換在Direct3D中,觀察矩陣由全局助手函數(shù)D3DXMatrixLookAtLH(Left-Handed,左手系)和D3DXMatrixLookAtRH(Right-Handed,右手系)來(lái)創(chuàng)建:圖13-15觀察變換D3DXMATRIX*D3DXMatrixLookAtLH(//創(chuàng)建左手系觀察矩陣(右手系:LH→RH)D3DXMATRIX*pOut,//結(jié)果矩陣CONSTD3DXVECTOR3*pEye,//眼睛位置點(diǎn)CONSTD3DXVECTOR3*pAt,//觀察目標(biāo)點(diǎn)(方向),通常取為原點(diǎn)(0,0,0)CONSTD3DXVECTOR3*pUp//觀察上方點(diǎn),通常取為y軸正向(0,1,0));可以通過(guò)這兩個(gè)函數(shù)之一(一般采用左手系的觀察矩陣函數(shù)),來(lái)獲得所需要的觀察變換矩陣。最后,也是需要使用D3DTS_VIEW狀態(tài)值,來(lái)調(diào)用IDirect3DDevice9接口的SetTransform方法,以實(shí)施矩陣所對(duì)應(yīng)的觀察變換。例如:D3DXMATRIXmatView;//定義觀察矩陣結(jié)構(gòu)D3DXVECTOR3eye(2,3,3);//設(shè)眼睛位置為(2,3,3)D3DXVECTOR3at(0,0,0);//設(shè)目標(biāo)點(diǎn)為原點(diǎn)D3DXVECTOR3up(0,1,0);//設(shè)y軸正向?yàn)樯戏紻3DXMatrixLookAtLH(&matView,&eye,&at,&up);//獲取觀察變換矩陣g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView);//實(shí)施觀察變換投影變換投影變換(projectiontransform)將觀察平截頭體(frustum,切割物體的兩個(gè)平面之間的立體部分)轉(zhuǎn)換為一個(gè)立方體形狀(cuboidshape)??拷^察點(diǎn)的物體,投影后會(huì)顯得大一些。參見(jiàn)圖13-16。圖13-16投影變換與觀察平截頭體 圖13-17觀察平截頭體的確定觀察平截頭體由fov(fieldofview,視場(chǎng)/視野)角度和前后剪切面(frontandbackclippingplanes)的(用z坐標(biāo)指定的)距離來(lái)決定,參見(jiàn)圖13-17。圖13-18投影變換將觀察平截頭體轉(zhuǎn)換為一個(gè)立方體投影矩陣是典型的縮放和透視投影(scaleandperspectiveprojection)變換,它將觀察平截頭體轉(zhuǎn)換為一個(gè)立方體,其原點(diǎn)也從右上角移到了中心。參見(jiàn)圖13-18。圖13-18投影變換將觀察平截頭體轉(zhuǎn)換為一個(gè)立方體Direct3D提供了下列6個(gè)全局函數(shù)來(lái)創(chuàng)建投影矩陣:創(chuàng)建左手系透視投影矩陣——D3DXMatrixPerspectiveLH;創(chuàng)建右手系透視投影矩陣——D3DXMatrixPerspectiveRH;創(chuàng)建基于視野的左手系透視投影矩陣——D3DXMatrixPerspectiveFovLH;創(chuàng)建基于視野的右手系透視投影矩陣——D3DXMatrixPerspectiveFovRH;創(chuàng)建定制的左手系透視投影矩陣——D3DXMatrixPerspectiveOffCenterLH。創(chuàng)建定制的右手系透視投影矩陣——D3DXMatrixPerspectiveOffCenterRH。其中最常用的是創(chuàng)建基于視野的左手系透視投影矩陣函數(shù):D3DXMATRIX*D3DXMatrixPerspectiveFovLH(//返回結(jié)果矩陣D3DXMATRIX*pOut,//結(jié)果矩陣FLOATfovY,//視角(弧度值)FLOATAspect,//水平視角與垂直視角的比例FLOATzn,//近觀察平面(前剪切面)的Z值(距離)FLOATzf//遠(yuǎn)觀察平面(后剪切面)的Z值(距離));其返回矩陣為:其中:yScale=tan(2/fovY)、xScale=yScale/Aspect與世界變換和觀察變換一樣,在獲得了投影變換矩陣后,也需要使用D3DTS_PROJECTION狀態(tài)值,來(lái)調(diào)用IDirect3DDevice9接口的SetTransform方法,以實(shí)施該矩陣所對(duì)應(yīng)的投影變換。例如:D3DXMATRIXA16matProj;//定義矩陣結(jié)構(gòu)//設(shè)置基于視野的左手系透視投影矩陣(45度視角、水平與垂直視角的比例為1、//Z值從1~100)D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,100.0f);g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);//實(shí)施投影變換剪切和窗口縮放視口(viewport)是一個(gè)(三維場(chǎng)景被投影到其中的)二維矩形。當(dāng)視口小于Direct3D的顯示表面(如屏幕)時(shí),就需要進(jìn)行裁剪(clipping)。參見(jiàn)圖13-19。在Direct3D中,定義了視口結(jié)構(gòu):typedefstructD3DVIEWPORT9{//視口結(jié)構(gòu)DWORDX;//視口矩形左上角的x坐標(biāo)DWORDY;//視口矩形左上角的y坐標(biāo)DWORDWidth;//視口矩形的寬度DWORDHeight;//視口矩形的高度圖13-19顯示表面與視口(結(jié)構(gòu))floatMinZ;//最小深度緩沖值圖13-19顯示表面與視口(結(jié)構(gòu))floatMaxZ;//最大深度緩沖值}D3DVIEWPORT9;可以用IDirect3DDevice9接口的SetViewport和GetViewport方法來(lái)設(shè)置和獲取視口:HRESULTSetViewport(CONSTD3DVIEWPORT9*pViewport);//設(shè)置視口HRESULTGetViewport(D3DVIEWPORT9*pViewport);//獲取視口例如:D3DVIEWPORT9vp(0,0,800,600,0,1);g_pd3dDevice->SetViewport(&vp);13.2.6光照、材質(zhì)與紋理幾何對(duì)象只有形狀和大小,而真實(shí)的物體還有材質(zhì)、紋理、重量、剛度、彈性等等其他物理特性,我們這里只討論影響其外觀的材質(zhì)和紋理。當(dāng)然,任何物體,如果沒(méi)有光線照射,你是什么也看不見(jiàn)的。所以,場(chǎng)景的最后觀看效果,還取決于燈光的設(shè)置。下面簡(jiǎn)單介紹Direct3D中的光照安排、材質(zhì)設(shè)置和紋理使用等的基本內(nèi)容。光照光照(light燈光)用于照亮三維場(chǎng)景中的物體。Direct3D提供了兩種燈光模式:環(huán)境光和直接光。環(huán)境光(ambientlight)是一種散射的光,沒(méi)有固定的方向,也不會(huì)產(chǎn)生陰影,可以照亮場(chǎng)景的任何地方。例如陰天。圖13-20直接光的種類聚光外角φ內(nèi)角θ光照區(qū)方向光點(diǎn)光圖13-20直接光的種類聚光外角φ內(nèi)角θ光照區(qū)方向光點(diǎn)光在Direct3D中定義了光結(jié)構(gòu)D3DLIGHT9:typedefstructD3DLIGHT9{光結(jié)構(gòu)D3DLIGHTTYPEType;//光類型D3DCOLORVALUEDiffuse;//光發(fā)出的漫射色D3DCOLORVALUESpecular;//光發(fā)出的反射色D3DCOLORVALUEAmbient;//光發(fā)出的環(huán)境色D3DVECTORPosition;//光源位置點(diǎn),方向光時(shí)被忽略D3DVECTORDirection;//光的方向(非0矢量),點(diǎn)光時(shí)被忽略floatRange;//范圍:光照距離的最大值,必須≤最大浮點(diǎn)值的平方根,方向光時(shí)被忽略floatFalloff;//下降:聚光時(shí)的內(nèi)角到外角的光線衰減值(0.0~1.0),一般取為1.0floatAttenuation0;//衰減0:光線強(qiáng)度和距離關(guān)系的計(jì)算權(quán)值0,取值0.0~∞floatAttenuation1;//Direct3D中光強(qiáng)衰減倍數(shù)A的計(jì)算公式(D為到光源的距離):floatAttenuation2;//floatTheta;//θ:聚光的內(nèi)角大小floatPhi;//φ:聚光的外角大小}D3DLIGHT9;其中:光類型枚舉D3DLIGHTTYPE定義為:typedefenumD3DLIGHTTYPE{//光類型枚舉D3DLIGHT_POINT=1,//點(diǎn)光D3DLIGHT_SPOT=2,//聚光D3DLIGHT_DIRECTIONAL=3,//方向光D3DLIGHT_FORCE_DWORD=0x7fffffff,//強(qiáng)制此枚舉類型的值為雙字}D3DLIGHTTYPE;浮點(diǎn)顏色值結(jié)構(gòu)D3DCOLORVALUE的定義為:(其中各字段的取值范圍為0.0~1.0)typedefstructD3DCOLORVALUE{floatr;floatg;floatb;floata;}D3DCOLORVALUE;其中,a為表示透明度的α值。矢量結(jié)構(gòu)D3DVECTOR的定義為:typedefstructD3DVECTOR{floatx,y,z;}D3DVECTOR;在定義并初始化了光結(jié)構(gòu)后,可以利用IDirect3DDevice9接口的SetLight方法,來(lái)設(shè)置場(chǎng)景的各個(gè)燈光:HRESULTSetLight(//成功返回D3D_OKDWORDIndex,//燈光的索引值(下同)CONSTD3DLight9*pLight//燈光的結(jié)構(gòu));可以對(duì)一個(gè)場(chǎng)景設(shè)置多個(gè)燈光,它們用各自的索引值來(lái)標(biāo)識(shí)。對(duì)同一索引值的再次燈光設(shè)置,將會(huì)覆蓋掉原來(lái)已有的設(shè)置。還可以利用IDirect3DDevice9接口的GetLight方法,來(lái)保存場(chǎng)景的燈光設(shè)置:HRESULTGetLight(DWORDIndex,D3DLight9*pLight);注意,Direct3D允許打開和關(guān)閉所設(shè)置的各個(gè)燈光,這可由IDirect3DDevice9接口的LightEnable方法來(lái)完成:HRESULTLightEnable(//成功返回D3D_OKDWORDLightIndex,//燈光的索引值BOOLbEnable//TRUE:開,F(xiàn)ALSE:關(guān));還可以利用IDirect3DDevice9接口的GetLightEnable方法,來(lái)獲取場(chǎng)景中的燈光開關(guān)情況:HRESULTGetLightEnable(DWORDIndex,BOOL*pEnable/*返回值*/);例如:D3DLight9d3dLight;//定義燈光結(jié)構(gòu)變量ZeroMemory(&D3dLight,sizeof(d3dLight));//初始化為0//設(shè)置白色電光d3dLight.Type=D3DLIGHT_POINT;d3dLight.Diffuse.r=1.0f; d3dLight.Diffuse.g=1.0f; d3dLight.Diffuse.b=1.0f;d3dLight.Ambient.r=1.0f; d3dLight.Ambient.g=1.0f; d3dLight.Ambient.b=1.0f;d3dLight.Specular.r=1.0f; d3dLight.Specular.g=1.0f; d3dLight.Specular.b=1.0f;//設(shè)置光源位置d3dLight.Position.x=0.0f; d3dLight.Position.y=1000.0f; d3dLight.Position.z=-100.0f;d3dLight.Attenuation0=1.0f;//無(wú)衰減d3dLight.Range=1000.0f;//最大距離if(g_pd3dDevice->SetLight(0,&d3dLight)==D3D_OK)//設(shè)置燈光g_pd3dDevice->LightEnable(0,TRUE);//打開燈光材質(zhì)材質(zhì)(material)是構(gòu)成物體的材料和質(zhì)地(如金屬、木頭、布料、鏡子等),它決定了物體表面隊(duì)光線的反應(yīng):如何反射光線,包括如何進(jìn)行鏡面反射和漫反射;在高光部分如何反射光線;是否自己發(fā)出光線沒(méi)有設(shè)置材質(zhì)的物體,不能反射任何光線。因此,即使場(chǎng)景中有光源,物體仍然顯示出一片黑暗,你什么也不會(huì)看到。所以,只有給場(chǎng)景的物體指定了材質(zhì),才會(huì)在顯示出正確的光照效果來(lái)。在Direct3D中,并沒(méi)有給出一個(gè)與自然物體(如木材、鋼鐵、布料等)對(duì)應(yīng)的材質(zhì)表,而是定義了一個(gè)可以設(shè)置物體反光特性的材質(zhì)結(jié)構(gòu)D3DMATERIAL9:typedefstructD3DMATERIAL9{//材質(zhì)結(jié)構(gòu)D3DCOLORVALUEDiffuse;//漫反射光線的顏色D3DCOLORVALUEAmbient;//環(huán)境反射光線的顏色D3DCOLORVALUESpecular;//(高光部分)鏡面反射光線的顏色D3DCOLORVALUEEmissive;//發(fā)射光線的顏色(光源)floatPower;//鏡面反射光線的強(qiáng)度}D3DMATERIAL9;可以利用IDirect3DDevice9接口的SetMaterial方法來(lái)為Direct3D設(shè)備設(shè)置材質(zhì):HRESULTSetMaterial(CONSTD3DMATERIAL9*pMaterial);//成功返回D3D_OK該材質(zhì)設(shè)置對(duì)后面所渲染的所有物體都有效。如果希望對(duì)不同的物體設(shè)置不同的材質(zhì),就必須在渲染每個(gè)物體前,重新設(shè)置Direct3D設(shè)備為對(duì)應(yīng)的材質(zhì)。你還可以利用IDirect3DDevice9接口的GetMaterial方法來(lái)獲取Direct3D設(shè)備的當(dāng)前材質(zhì)設(shè)置:HRESULTGetMaterial(D3DMATERIAL9*pMaterial/*返回材質(zhì)設(shè)置*/);例如:D3DMATERIAL9mat;//定義材質(zhì)結(jié)構(gòu)變量//設(shè)置漫反射顏色值RGBAmat.Diffuse.r=0.5f; mat.Diffuse.g=0.0f; mat.Diffuse.b=0.5f; mat.Diffuse.a=1.0f;//設(shè)置環(huán)境反射顏色值RGBAmat.Ambient.r=0.5f; mat.Ambient.g=0.0f; mat.Ambient.b=0.5f; mat.Ambient.a=1.0f;//設(shè)置鏡面反射顏色值和強(qiáng)度mat.Specular.r=1.0f; mat.Specular.g=1.0f; mat.Specular.b=1.0f; mat.Specular.a=1.0f;mat.Power=50.0f;//設(shè)置發(fā)射顏色值RGBAmat.Emissive.r=0.0f; mat.Emissive.g=0.0f; mat.Emissive.b=0.0f; mat.Emissive.a=0.0f;g_pd3dDev->SetMaterial(&mat);//設(shè)置設(shè)備材質(zhì)紋理紋理(texture)是物體的表面圖形特征(花紋),它比單一的表面顏色更逼近真實(shí)。在Direct3D中,紋理實(shí)際上被定義為覆蓋在物體表面的矩形平面圖像。為了將紋理覆蓋在物體表面上,需要確定紋理在物體表面上的位置,稱之為紋理坐標(biāo)。在Direct3D中,定義了一個(gè)統(tǒng)一的紋理坐標(biāo)系,其紋理坐標(biāo)的取值范圍為規(guī)范為0.0~1.0。紋理中單個(gè)的顏色值,稱為紋理元素(texel=textureelement)。參見(jiàn)圖13-21。為了在物體表面上使用紋理,在定義頂點(diǎn)格式時(shí),必須考慮紋理坐標(biāo)(x,y)。例如:structCUSTOMVERTEX{//頂點(diǎn)結(jié)構(gòu)D3DXVECTOR3position;//位置D3DCOLORcolor;//顏色FLOATtu,tv;//紋理坐標(biāo)圖13-21紋理坐標(biāo)與映射}圖13-21紋理坐標(biāo)與映射對(duì)應(yīng)的宏常量定義也改為:#defineD3DFVF_CUSTOMVERTEX(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)在Direct3D中,定義了多種紋理接口,其中最主要的是IDirect3DTexture9。在Direct3D中,創(chuàng)建紋理的最簡(jiǎn)單的方法是,調(diào)用全局函數(shù)D3DXCreateTextureFromFile:HRESULTD3DXCreateTextureFromFile(//成功返回D3D_OKLPDIRECT3DDEVICE9pDevice,//設(shè)備指針LPCTSTRpSrcFile,//圖像文件路徑串LPDIRECT3DTEXTURE9*ppTexture//返回的紋理接口指針);來(lái)從一個(gè)圖像文件來(lái)產(chǎn)生紋理,它所支持的圖像文件格式有:BMP、DDS、DIB、HDR、JPG、PFM、PNG、PPM和TGA,但是不支持GIF格式。然后,我們可使用IDirect3DDevice9接口的SetTexture方法,來(lái)設(shè)置Direct3D設(shè)備的當(dāng)前紋理狀態(tài):(似材質(zhì)設(shè)置,對(duì)后面渲染的物體有效)HRESULTSetTexture(//成功返回D3D_OKDWORDSampler,//采樣器編號(hào),用于可編程渲染的參考紋理和紋理層次編號(hào)IDirect3DBaseTexture9*pTexture//紋理接口指針(NULL=清除紋理));例如:LPDIRECT3DTEXTURE9g_pTexture=NULL;if(D3DXCreateTextureFromFile(g_pd3dDevice,"picture.bmp

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論