RenderMonkey基本使用方法【轉】


RenderMonkey基本使用方法

楔子:
  差不多從年中開始由於工作需要,開始研究Direct3D,這是繼大二開始自學DX開始,睽違了6年后再重新學習DX。雖然時間很久了,但是幸虧還是有點基礎,所以上手還是比較順利的。當然由於DX本身難度就比較大,再經過了一兩個月的熟悉后,后來發現剛開始寫的代碼很累贅很復雜且不知所以,所以說脫離實際的自學與實際中根據目標的自學所學到的東西是完全兩碼子事兒,這就是所謂的“博學而篤志,近問而切思,仁在其中矣”,不要好高騖遠,不要脫離實際。
  好了,廢話說了這么多,該說正經的了。在重新出發學習DX的時候,尤其是Shader的時候,因為隱約記得大學自學的時候並沒有接觸這一塊,所以上手就稍微費力了一點,特別是關於Shader的資料很難找到入門級的,大多數都在DXSDK中零星的分布。當然這里我並不想也沒有那個水平去寫一篇Shader的教程,只是想分享一下自己在學習Shader過程中使用到的一個工具--AMD的RenderMonkey。
  關於RenderMonkey的使用,最基本的當然是參看其自帶的SDK文檔了,但是這個SDK除了介紹RenderMonkey的使用方法外,幾乎沒有其它與Shader相關的部分,這是很痛苦的。后來從網上狗狗也只找到些許與RenderMonkey相關的文章,當然寫的很好,有基礎入門的,也有提高篇的,但是有個唯一的缺點就是,它們使用的都是老版本的RenderMonkey,而我現在則使用AMD最新版本的RenderMonkey,其界面和使用方法與老版本是有一定差異的,所以只有靠自己摸索了。下面正式開始~

////////////////////////////////////////////////// 華麗的分割線 /////////////////////////////////////////////////////////

  首先,從AMD開發者網站上下載最新版本的RenderMonkey,截至到本文發布之時,可以下到1.82版本的RenderMonkey。安裝很簡單,一路Next下去就OK。雙擊運行,彈出的Splash,果然就是一只猴子,囧~程序的界面,嗯,長的和VC6很像嘛!!
Effect Workspace就和VC6中的Solution的概念相似,即可以在這個名為"Effect Workspace"的解決方案下添加不同的“Project”。當然,在RenderMonkey中Effect Workspace是作為“根”(Root)節點出現的,其下可以添加其它的子節點,這點上並不像VC的Project了。
  現在可以嘗試在“Effect Workspace”這個根節點下添加其它的子節點,就是在這個根節點上點擊鼠標右鍵,會發現彈出一個多級菜單,這其中有許多選項我都不打算去觸碰,因為我也沒有完全搞清楚 。現在先來看看“Add Effect Group”,其實這個很像VC6中添加一個文件夾,其實只是為了方便管理代碼而已,本身不會影響代碼的運行。
  回想在VC中,當我們創建一個空的Project后,可以自己添加.h/.cpp/.rc。但如果我們使用了VC自帶的工程向導的話,就很簡單地就可以創建一個應用程序,例如一個基於MFC的對話框程序等等,然后我們就可以在這個工程上根據自己的需要修改相應的.h/.cpp來實現自己所需要的功能。同樣地,在RenderMonkey也有類似的操作,你既可以在一個空的Effect Workspace上單獨添加一個一個節點,也可以直接使用RenderMonkey提供的默認所謂的“Default Effect”,然后我們在這個Default Effect上根據自己的需要進行修改。這里,我們使用RenderMonkey默認的最簡單的DX效果Add Default Effect->DirectX->DirectX。
經過這樣的操作后,可以看到在渲染窗口中出現了一個紅色的球體。展開Default_Direct_Effect節點后的結果也如圖所示,可以看到有很多奇怪的節點圖標,下面就一一為您詳解它們的前世今生 。(還請先閱讀一下RenderMonkey的SDK文檔了解相關知識)
  matViewProjection是RenderMonkey提供的預定義變量(類型為4*4矩陣),之所以知道是“預定義”,是因為這個圖標左下角有一個綠色的P字母,代表PreDefined。這里出現的matViewProjection節點相當於固定管線中聲明並定義了一個4*4的矩陣變量。
  接下來的Stream Mapping節點不知道翻譯為“流映射”節點是否合適?該節點的作用是綁定數據流到輸入寄存器中供shaders使用。RenderMonkey將會直接使用來自模型的數據來自動產生這個流(例如前面我們下面將要講到的Model節點就只有位置信息,那么如果你雙擊這個Stream Mapping節點,就會看到POSITION信息了。)或者你通過用戶接口來定義流通道,然后由應用程序獲取和輸出該流中的信息。按照我的理解,這個Stream Mapping實際上對應了固定管線中聲明FVF的過程,而下面的流映射參考節點(Stream Mapping Reference)則對應了固定管線中的IDirect3DDevice9::SetFVF函數的功能。
  Model節點是做什么的呢?一個Effect要通過一個幾何模型才能過表現出來,即要有一個載體。RenderMonkey用模型(Model)和模型參考(Model Reference)節點來允許用戶指定哪個模型被渲染。按照我的理解,設置Model節點就是固定管線中的根據FVF創建頂點緩沖並對其賦值的過程,而Model Reference則是固定管線中IDirect3DDevice9::SetStreamSource的調用,指示當前的渲染對象是哪些頂點(這些Vertext即構成了這里的Model)。
  一個效果至少要有一個Pass(這說明RenderMonkey中的效果實際上也和固定管線中IEffect的概念一樣),默認為Pass 0。在Pass節點中包含的大多是引用類型的節點(除了Shader之外)。
  Pass中一般有兩個Shader:Vertex Shader和Pixel Shader,分別代表頂點着色器和像素着色器,這兩個節點是整個Effect中最重要也是唯一需要編寫代碼的地方。
  在Vertex Shader中:首先聲明了一個類型為float4x4的全局變量matViewProjection,可以看到這個變量的名字和左邊Workspace 內的matViewProjection節點的名字一樣,這並不是巧合!回想在固定管線中向Shader傳送變量的過程,我們首先從IEffect接口中獲取Shader中某個全局變量的對應的D3DXHANDLE,然后就可以向這個D3DXHANDLE中傳遞參數(被映射到Shader的全局變量上),而這個參數最終被用在Shader中。在RenderMonkey中,沒有固定渲染管線這個玩意兒,那么它是怎樣實現向Shader中傳入參數的操作的呢?答案就是Workspace中的變量節點和Shader中定義的全局變量是同名名字。就是說如果你想在Shader中使用外部傳入的變量參數的話,就必須聲明一個名字和類型都和Effect節點下一致的節點,而我們在Workspace中是可以直接雙擊某個可編輯的節點進行編輯的(當然這個節點必須是可以“被編輯的 ”,而例如RM預定義的那些變量就是不可被編輯的),那么就相當於實時的改變了Shader中相應的全局變量。
  Pixel Shader的用法也大概和Vertex Shader和一樣。
  在Effect中添加一個紋理也是很簡單的,例如如果想添加一個2D紋理,那么就直接Add Texture->Add 2D Texture->2D Texture(這里不使用RM資源庫中預先定義好的紋理),這樣就創建了一個空的紋理,而如果想將其綁定到某個圖像文件,就可以直接雙擊該節點並選擇一個圖像即可。這一步就相當於固定管線中的D3DXCreateTextureFromFile一樣。類似於模型參考和流映射參考,我們還需要在Pass中添加一個紋理對象(Texture Object,為什么不叫Texture Reference呢?不曉的),並將其指向剛剛創建的紋理。感覺這一步就像是固定管線中的IDirect3DDevice9::SetTexture一樣。而雙擊這個紋理對象后,就更會發現一些與固定管線中函數SetSamplerState和SetTextureStageStatus相似的東東了,而且可以對它們進行設置,就像SetSamplerState和SetTextureStageStatus所做的事情一樣。
  OK,基本上,DirectX的Default Effect上的基本元素就這么多了,個人所理解的也只有這么多了 ,下面來看看Shader中最常用到的Render Target究竟時個什么玩意兒!

  關於RenderTarget的概念,可以參見RenderMonkey中默認的DirectX Effect--“Render To Texture”實例。我們可以先刪除這個例子下的RenderTarget相關的節點,然后來學習如何使用RenderTarget--首先需要在Workspace下創建一個Renderable Texture節點,雙擊這個節點會發現一些有趣的東西,如Width/Height/Format,這些怎么這么眼熟?不就是IDirect3DDevice9::CreateTexture中的一些參數一致么?既然創建了RenderTarget,那么就要首先在這個RenderTarget中做一些渲染的操作,具體來說,就是在第一個Pass中Add Render Target並將其“指向”剛才添加的Renderable Texture(這似乎和以前的添加參考對象是一樣的含義?),雙擊這個節點(就是前面有一個紅色圓心的節點),又可以發現一些與固定管線相像的玩意兒:Clear?Depth Buffer?可以猜想,這個操作實際與固定管線中如下代碼是一樣的含義:
  g_pD3D9Device->GetRenderTarget(0, &pOldRenderTarget);
  g_pRenderTarget->GetSurfaceLevel(0, &pRenderSurface);
  g_pD3D9Device->SetRenderTarget(0, pRenderSurface);
  g_pD3D9Device->Clear(0, 0, D3DCLEARTARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_X#000000, 1, 0);
RenderMonkey中並沒有顯式的獲取Old RenderTarget和恢復Old RenderTarget的過程,但是這卻是固定管線中必須有的,所以可以肯定RenderMonkey也一定做了相同的動作,只是不給我們看而已。
  渲染完RenderTarget后,就需要回到原來的幀緩存中(即調用IDirect3D9Device::SetRenderTarget將原來保存的Old RenderTarget恢復回去,這一步在RenderMonkey里面是看不到的),並將已經渲染好的Renderable Texture設置到設備的某個紋理層上即可。在RenderMonkey中表現為在第二個Pass中(注意,該Pass的Index號必須比上述渲染RenderTarget的Pass要大,即一定要先渲染RenderTarget再渲染幀緩存),創建一個普通的紋理對象Add Texture Object並將其指向Renderable Texture,就和使用普通的紋理一樣。
  多個RenderTarget的渲染和單個比起來並沒有什么不同,只是多了幾個節點而已。但是有一點要強調的是當在一個Pass中出現多個紋理對象的時候,它們實際上是安裝多“層”紋理而不是多“次”紋理來渲染的,因為當我們把鼠標移動到Texture Object節點上時候可以看到會提示到“Texture Stage x”,其中x為0開始的數字,這難道不會讓你聯想到固定管線中的SetTexture的第一個參數或者SetTextureStage函數么?

  OK,關於RenderMonkey的幾個基本節點(實際上個人才疏學淺,目前也只了解這些了)就到此到一段落了。以后有時間再講講如何將RenderMonkey中編寫好的Shader文件直接交予應用程序使用,因為畢竟使用RenderMonkey來設計編寫調試Shader代碼是比較方便的


參考資料:
1.《RenderMonkey Toolsuite》
http://developer.amd.com/gpu/rendermonkey/Pages/default.aspx
2.《用RenderMonkey進行shader開發》
http://school.ogdev.net/ArticleShow.asp?id=5551&categoryid=5
http://school.ogdev.net/ArticleShow.asp?id=5552&categoryid=5
3.《Direct3D提高篇:HLSL編程實現PhotoShop濾鏡效果》
http://tech.it168.com/n/2007-03-29/200703291522292.shtml


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM