yag Site Admin
註冊時間: 2007-05-02 文章: 689
2704.11 果凍幣
|
發表於: 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 |
從以上可以看得出來,幾乎絕大多數的關鍵字、示意字等都沒有大小寫差異
只有少數關鍵字必須完全小寫,目前我還沒發現有需要完全大寫的關鍵字 |
|