電腦遊戲製作開發設計論壇 首頁 電腦遊戲製作開發設計論壇
任何可以在PC上跑的遊戲都可以討論,主要以遊戲之製作開發為主軸,希望讓台灣的遊戲人有個討論、交流、教學、經驗傳承的園地
 
 常見問題常見問題   搜尋搜尋   會員列表會員列表   會員群組會員群組   會員註冊會員註冊 
 個人資料個人資料   登入檢查您的私人訊息登入檢查您的私人訊息   登入登入 

Google
3D遊戲程式設計入門第19章心得

 
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫
上一篇主題 :: 下一篇主題  
發表人 內容
yag
Site Admin


註冊時間: 2007-05-02
文章: 688

2673.35 果凍幣

發表發表於: 2010-3-11, AM 9:02 星期四    文章主題: 3D遊戲程式設計入門第19章心得 引言回覆

前言:此乃補丁文。只講解心得,不提供完整教學,有興趣的人請自行購買此書。
代碼:
書名:3D遊戲程式設計入門-使用DirectX 9.0實作
作者:Frank D. Luna
譯者:黃聖峰
出版社:博碩文化


關於Pass
如果裝了較新SDK的人在compile第19章範例時會發現有下面這個error:
代碼:
error C2039: 'Pass' : is not a member of 'ID3DXEffect'

因為DXSDK在大約2004~2005年版之後的SDK裡將Pass函式從ID3DXEffect介面中移除了
相對新增的是BeginPass與EndPass這兩個函式
使用方式很簡單,將原先的Pass改成BeginPass,然後在呼叫Pass的迴圈的底部加個EndPass即可
大致是將
代碼:
for(int i = 0; i < numPasses; i++)
{
   Effect->Pass(i);

   for(int j = 0; j < Mtrls.size(); j++)
   {
      Mesh->DrawSubset(j);
   }
}

改成這樣:
代碼:
for(int i = 0; i < numPasses; i++)
{
   Effect->BeginPass(i);

   for(int j = 0; j < Mtrls.size(); j++)
   {
      Mesh->DrawSubset(j);
   }

   Effect->EndPass();
}

因為修改很簡單,所以就不把三個範例的修改一一講述了。

關於ValidateTechnique
照書上所說,我們在SetTechnique之前應該使用ValidateTechnique來檢驗硬體是否能支援該特效檔
不過範例中大概是為了集中焦點,所以並沒有使用這個函式
在此我提供一個大致的範例:
代碼:
HRESULT hr = 0;

hr = Effect->ValidateTechnique( TechHandle );

if( FAILED( hr ) )
{
   ::MessageBox( 0, "Technique() - FAILED", 0, 0 );
   Device->EndScene();
   return false;
}

以上這段只要稍加修改,放在範例中呼叫BeginScene與呼叫SetTechnique的兩敘述中間即可
一樣不一一贅述。

Lithting and Texturing
此範例中我有注意到了一些現象
或許你們也有注意到,或者沒注意到
總之,我在此記錄一下,與大家分享

一、Texture在設定給Effect的參數後就可以Release掉,如下:
代碼:
IDirect3DTexture9* tex = 0;
D3DXCreateTextureFromFile(Device, "Terrain_3x_diffcol.jpg", &tex);

LightTexEffect->SetTexture(TexHandle, tex);

d3d::Release<IDirect3DTexture9*>(tex);

雖然我們還沒把tex拿來draw
不過只要設定給TexHandle
似乎是LightTexEffect會自行備份一份
於是tex就可以Release掉了
不用等到Cleanup()函式被呼叫時再Release

二、Mesh的subset數量是由Mtrls的數量來決定:
代碼:
for(int j = 0; j < Mtrls.size(); j++)
{
   Mesh->DrawSubset(j);
}

這個在之前的章節中我都沒有特別的意識到
實際上這個用法已經出現過數次
Mesh本身並沒有記錄它的subset數量
要由我們在呼叫D3DXLoadMeshFromX之後自行從傳回的numMtrls引數來取得並記錄下來

三、Mtrls跟Textures都沒有使用到
我們自行讀了個tex進來並把它設給LightTexEffect的參數
並且在technique LightAndTexture的pass P0中,我們自行填寫了一個Material
所以Mtrls唯一的用處是記錄Mesh的subset數量 -- 實際上我們只需要一個int去記錄它
我看不出來在這個範例中建立這兩個全域std::vector的必要性
或許這只是舊範例的遺物
但這讓我想到一個問題
當我們的Mesh需要使用複數的材質與質料時,我們該怎麼設定呢?
似乎很難延用此範例的設定法吶

Fot Effect
此範例應該是延用第13章的範例來修改的
所以Camera類別、Lerp函式、Terrain類別跟Display函式中pitch的呼叫等等相關修改請參考第13章的心得

在此範例的technique Fog中有下面幾行:
代碼:
fvf              = XYZ | Normal;
Lighting         = true;
NormalizeNormals = true;

實際上這些都是沒用處的
因為在BeginPass後,我們呼叫的是Terrain類別的draw函式
在此函式中,我們有自行設定了FVF以及Lighting相關功能
這應該會取代掉technique Fog中的設定
畢竟Terrain類別的FVF可是只有 XYZ | TEX1 的頂點結構
要真用了 fvf = XYZ | Normal; 的話
恐怕會出問題吧?

另外,雖然我們在Terrain類別的draw函式中,於畫格線時有打開打光效果
但是我們並沒有設定任何燈光,所以得到的格線一樣會是黑的

CartoonEffect
在此範例中有些code沒有用到,應該也是舊範例的遺物,如:
代碼:
IDirect3DTexture9* ShadeTex  = 0;

跟Cleanup()函式中的
代碼:
d3d::Release<IDirect3DTexture9*>(ShadeTex);


此範例中,把Pass改成BeginPass後,依然會有問題
原因是在BeginPass後才呼叫Effect->Set*相關的函式的話
必須在draw前加上一行ID3DXEffect::CommitChanges的呼叫
所以要像這樣修改:
代碼:
ToonEffect->SetMatrix(WorldViewHandle, &WorldView);
ToonEffect->SetMatrix(WorldViewProjHandle, &WorldViewProj);
ToonEffect->SetVector(ColorHandle, &MeshColors[j]);
Meshes[j]->DrawSubset(0);

將以上改成:
代碼:
ToonEffect->SetMatrix(WorldViewHandle, &WorldView);
ToonEffect->SetMatrix(WorldViewProjHandle, &WorldViewProj);
ToonEffect->SetVector(ColorHandle, &MeshColors[j]);
ToonEffect->CommitChanges();
Meshes[j]->DrawSubset(0);

如此才能正常繪製
否則的話,DX會抓"最後"設置的Matrix跟Color來設定所有的Mesh
很奇怪沒錯,我也不知道為啥會是抓最後而不是抓最初
但反正會有錯,要加上CommitChanges才行
另外一修正方式,則是將SetMatrix等函式提到BeginPass之前呼叫
等設定完Effect參數,再呼叫BeginPass,如此就可以正常執行

關於特效檔中的關鍵字與其大小寫差異
此章是本書最後一章
看到這裡,我發現effect或shader裡有些地方很可能會誤導讀者
以下是我列出看似關鍵字,實際上不是關鍵字的名稱:
代碼:
Main
VS_INPUT
VS_OUTPUT
PS_INPUT
PS_OUTPUT

以上在書中有說"Main"可以自訂,不過卻沒提到關於INPUT、OUTPUT相關的結構名稱
我一直到看完此章都還以為這些名稱是關鍵字
直到我實際測試過後才發現這些都不是關鍵字
也就是說,你可以將tooneffect.txt中的
代碼:
struct VS_INPUT
{
    vector position : POSITION;
    vector normal   : NORMAL;
};

struct VS_OUTPUT
{
    vector position : POSITION;
    float2 uvCoords : TEXCOORD;
    vector diffuse  : COLOR;
};

VS_OUTPUT Main(VS_INPUT input) { ... }

改成
代碼:
struct A
{
    vector position : POSITION;
    vector normal   : NORMAL;
};

struct B
{
    vector position : POSITION;
    float2 uvCoords : TEXCOORD;
    vector diffuse  : COLOR;
};

B Main(A input) { ... }

這樣是可行的
當然Main中也要做相對應的名稱修改

另外書中也並沒有提到關於關鍵字的大小寫差異的問題
經過我的測試,將其列表如下:
大小寫有差異的:
代碼:
sampler_state
sampler
compile
vs_1_1(及同類關鍵字)


大小寫沒有差異的:
代碼:
PASS中的所有屬性都沒有大小寫問題,如
   -- vertexshader
   -- pixelshader
   -- Lighting
   -- FogStart
   ...
   
sampler_state裡的所有屬性也都沒有大小寫問題,如
   -- Texture
   -- MinFilter
   -- MagFilter
   ...

變數與參數型態都沒有大小寫問題,如
   -- texture
   -- vector
   -- matrix
   ...

VS_INPUT之類輸入輸出結構裡的語意關鍵字也沒有大小寫問題,如
   -- POSITION
   -- NORMAL
   -- TEXCOORD
   -- COLOR
   ...
   
各種屬性的內建值示意字也沒有大小寫問題,如
   -- POINT
   -- NONE
   -- null
   -- XYZ(FVF的值)
   -- Normal(FVF的值)
   -- Tex1(FVF的值)
   -- true
   -- LINEAR
   ...
   
其他沒大小寫問題的:
technique
pass


從以上可以看得出來,幾乎絕大多數的關鍵字、示意字等都沒有大小寫差異
只有少數關鍵字必須完全小寫,目前我還沒發現有需要完全大寫的關鍵字
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
從之前的文章開始顯示:   
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫 所有的時間均為 台灣時間 (GMT + 8 小時)
1頁(共1頁)

 
前往:  
無法 在這個版面發表文章
無法 在這個版面回覆文章
無法 在這個版面編輯文章
無法 在這個版面刪除文章
無法 在這個版面進行投票
可以 在這個版面附加檔案
可以 在這個版面下載檔案


Powered by phpBB © 2001, 2005 phpBB Group
正體中文語系由 phpbb-tw 維護製作