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

Google
3D遊戲程式設計入門第16、17章心得[未解之疑問篇]

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


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

2673.35 果凍幣

發表發表於: 2010-3-6, PM 10:41 星期六    文章主題: 3D遊戲程式設計入門第16、17章心得[未解之疑問篇] 引言回覆

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


第16章
此章只有一個疑問,書上第16.3.6節有個範例:
代碼:
typedef float point2[2];

看不懂這是什麼,大致來說這應該是讓我們可以用point2[2]代替float
先不管point2是什麼
重點是這個類型要怎麼宣告變數?像下面這樣從
代碼:
float x;

改成
代碼:
point2[2] x;

是這樣做嗎?可是看起來怎麼好像不太合乎c++語法?
不知道有沒有c++高手可以幫忙解釋一下

第17章
前言
此章疑問暴多…而且因為最近比較忙,實在沒時間一一去測試看看
因此暫且先把所有疑問都記錄下來
有一些應該寫個範例程式就可以得知答案的問題
就等我有空後再去實作看看吧

心得
書上有提到,材質過濾功能會企圖使色彩的轉換變得平滑。
而卡通著色法要的是突兀的變換,因此我們必須用以下的方式把材質過濾功能關掉:
代碼:
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);


順便記錄個英文字:lit
它是light的過去式及過去分詞
我本來一直以為light的三態是light light light
這次恰好看到才知道以前都搞錯了

在範例VS Toon 2 With Outlines的SilhouetteEdges類別中
我們可以看到傳入的ID3DXMesh* mesh會被巢狀地多次LockVertexBuffer跟LockIndexBuffer
說實在的,我"又"本來一直以為沒有Unlock之前不可以再次Lock
但是程式跑得很順,可見我是錯的
就不知道這跟第一參數的flags有沒有關係
或許傳入某些flags的情況下我會是對的

SilhouetteEdges類別的getFaceNormals函式中
有三個很類似的區塊,分別設定faceNormal0、faceNormal1跟faceNormal2
以下是設定faceNormal0的區塊:
代碼:
if( faceIndex0 != USHRT_MAX ) // is there an adjacent triangle?
{
   WORD i0 = indices[faceIndex0 * 3];
   WORD i1 = indices[faceIndex0 * 3 + 1];
   WORD i2 = indices[faceIndex0 * 3 + 2];

   D3DXVECTOR3 v0 = vertices[i0].position;
   D3DXVECTOR3 v1 = vertices[i1].position;
   D3DXVECTOR3 v2 = vertices[i2].position;

   D3DXVECTOR3 edge0 = v1 - v0;
   D3DXVECTOR3 edge1 = v2 - v0;
   D3DXVec3Cross(&faceNormal0, &edge0, &edge1);
   D3DXVec3Normalize(&faceNormal0, &faceNormal0);
}
else
{
   faceNormal0 = -(*currentFaceNormal);
}

而以上的程式實際上可以改成如下:
代碼:
if( faceIndex0 != USHRT_MAX ) // is there an adjacent triangle?
{
   getFaceNormal(mesh, faceIndex0, &faceNormal0);
}
else
{
   faceNormal0 = -(*currentFaceNormal);
}

getFaceNormal也是SilhouetteEdges類別原有的函式
作者明明就寫了一個這樣的函式
卻不使用它,反而寫了落落長的三大區塊,真是令人不明白原因所在
另外USHRT_MAX的值是0xffff,但因為faceIndex0是WORD型態
所以此值即為-1,在adjacency buffer中,-1代表該邊緣沒有相鄰的三角形

在toon.cpp的Display函式中
繪製MeshOutlines之前,程式有先把背面剔除功能關掉:
代碼:
Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

雖然我不是很確定為什麼,但我認為跟SilhouetteEdges類別的genEdgeVertices函式有關
當初在看該函式時,我一直不能理解作者為什麼會以v0→v1、v1→v2、v0→v2這樣的順序來分別填入三個邊緣的A跟B點
以我的看法,v0、v1、v2因為是從index buffer按順序取出的,所以應該是個順時針排列的三頂點
根據genEdgeIndices函式中設定的索引順序來看
使用v1→v0、v2→v1、v0→v2這樣的順序來填A跟B點應該才能夠得到正確的繪製順序
不過這一切在把背面剔除功能關掉後就都不再重要了
反正背面不會被剔除,那麼順時針畫、逆時針畫,應該都會顯示出該邊緣方形
我想這一行應該就是這個用意,至於這麼做的原因,或許跟mesh可能以右手座標系塑模有關?
我沒仔細去思考過,等我有空後再試試看吧

當我們要使用IDirect3DVertexDeclaration9來自訂頂點格式時
如果要呼叫CreateVertexBuffer來建立頂點緩衝器
我們只需要單純地把第三參數原本填入FVF的位置填0即可
相關範例可在SilhouetteEdges::genEdgeVertices函式中看到

疑問
在書上到目前為止的shader範例中
頂點法向量跟光線向量都要先轉換到視覺空間後才能計算打光的陰影度
為什麼要這樣做?為什麼不可以在世界空間中計算打光?
又為什麼它可以直接把w分量設成0?
雖然我知道向量的w分量應該要設成0
但是它不用先做什麼處理嗎?
像是先做些轉換使w分量等於1之類的
另外書上有說作者假設世界矩陣並未進行任何縮放動作。因為如果有縮放,則它可能會混淆乘上它的向量的長度及方向。
那為什麼不用假設View矩陣並未進行任何縮放動作?
如果世界矩陣有縮放的話,又該如何處理?
以上所述的範例如下:
代碼:
VS_OUTPUT Main(VS_INPUT input)
{
   VS_OUTPUT output = (VS_OUTPUT)0;

   output.position = mul(input.position, WorldViewProjMatrix);

   LightDirection.w = 0.0f;
   input.normal.w   = 0.0f;
   LightDirection   = mul(LightDirection, WorldViewMatrix);
   input.normal     = mul(input.normal, WorldViewMatrix);

   float u = dot(LightDirection, input.normal);

   if( u < 0.0f )
      u = 0.0f;

   float v = 0.5f;

   output.uvCoords.x = u;
   output.uvCoords.y = v;

   output.diffuse = Color;
   
   return output;
}


從Toon相關的範例可以看得出來
Texture跟頂點輸出的diffuse會混色
但是它們是怎麼混色的呢?公式是什麼?直接相加嗎?
如果頂點的diffuse會跟Texture混色
那麼Material跟Texture也會混色嗎?
另外FVF彈性頂點格式中,我們也可以設置一個diffuse頂點色
在不使用shader的情況下
此diffuse頂點色也會跟Texture混色嗎?就跟shader輸出的diffuse一樣?
在第4章中曾經有介紹過著色法
該章節中設定的著色法也會影響到shader嗎?

在SilhouetteEdges::genEdgeVertices中
我們會將C點跟D點的頂點法向量設為邊緣兩頂點原先的頂點法向量
為什麼要這樣做呢?不可以將C點跟D點的頂點法向量直接設為我們求出的該面法向量currentFaceNormal嗎?

在書中的圖17.8裡,我們可以看到觀察方向與v向量(觀察點到目前傳入shader的頂點的向量)不見得是同一條向量
如果兩者之間有小角度存在,得到的邊緣檢驗結果不會有些微誤差嗎?
而且一個邊緣有兩個頂點,假設為v0跟v1
其分別算出的v向量(v0 - 原點)跟(v1 - 原點)取得的邊緣檢驗結果一定會一樣嗎?
以下是邊緣檢驗範例的shader:
代碼:
input.position = mul(input.position, WorldViewMatrix);

vector eyeToVertex = input.position;

input.normal.w      = 0.0f;
input.faceNormal1.w = 0.0f;
input.faceNormal2.w = 0.0f;

input.normal      = mul(input.normal,      WorldViewMatrix);
input.faceNormal1 = mul(input.faceNormal1, WorldViewMatrix);
input.faceNormal2 = mul(input.faceNormal2, WorldViewMatrix);

float dot0 = dot(eyeToVertex, input.faceNormal1);
float dot1 = dot(eyeToVertex, input.faceNormal2);

if( (dot0 * dot1) < 0.0f )
{
     input.position += 0.1f * input.normal;
}


在SilhouetteEdges類別中,我們為什麼可以假設mesh是用MeshVertex形式的頂點?
代碼:
struct MeshVertex
{
   D3DXVECTOR3 position;
   D3DXVECTOR3 normal;
   static const DWORD FVF;
};

是因為
D3DXCreateTeapot
D3DXCreateSphere
D3DXCreateTorus
D3DXCreateCylinder
此四函式得到的mesh都剛好是這種頂點嗎?
最後,我們真的需要MeshVertex::FVF嗎?看起來好像沒什麼作用
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
撲殺兔
時常出沒的會員


註冊時間: 2009-05-18
文章: 30

219.89 果凍幣

發表發表於: 2011-8-2, PM 4:05 星期二    文章主題: 引言回覆

typedef float point2[2]; 是指定義 point2 為一個擁有兩個 float 元素的陣列,

使用的時候是

point2 x = {2.56, 9.84}; 存取個別元素時用 x[0], x[1]

ps. 可以請版主若日後搞懂了問題把後來的想法以回文或編輯原文的方式補充嗎, 我想這樣對其他人還是會有幫助的(至少對我= =)
回頂端
檢視會員個人資料 發送私人訊息
yag
Site Admin


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

2673.35 果凍幣

發表發表於: 2011-8-2, PM 6:05 星期二    文章主題: 引言回覆

撲殺兔 寫到:
typedef float point2[2]; 是指定義 point2 為一個擁有兩個 float 元素的陣列,

使用的時候是

point2 x = {2.56, 9.84}; 存取個別元素時用 x[0], x[1]

ps. 可以請版主若日後搞懂了問題把後來的想法以回文或編輯原文的方式補充嗎, 我想這樣對其他人還是會有幫助的(至少對我= =)

原來如此,感謝解答 Very Happy
話說我現在已經改成在研究web game了,許久沒寫過c++跟dx…
如果日後我有機會弄懂這些問題的話,我會來補充的,不過短期內應該機會不大 XD
回頂端
檢視會員個人資料 發送私人訊息 發送電子郵件
從之前的文章開始顯示:   
發表新主題   回覆主題    電腦遊戲製作開發設計論壇 首頁 -> 遊戲程式高級班:DirectX、OpenGL及各種圖型函式庫 所有的時間均為 台灣時間 (GMT + 8 小時)
1頁(共1頁)

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


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