2008年7月31日 星期四

每個人都是韓國人

繼成功的將孔子歸化為韓國人之後,韓國的大學教授們,又將孫中山先生歸化為韓國人。

教授說,有一支古朝鮮人軍隊為周朝作戰,其中一群人由於戰功彪炳,被周文王冊封於孫。這就是孫氏的起源,所以孫中山先生有韓國人血統。

那麼,孫悟空應該也是韓國人。

朋友問我,『這些韓國人到底是什麼心態?』,我說,『就像是歐洲的有錢人,想去買個貴族爵位來坐坐一樣』。

『不懂』。

『你們這些泱泱大國,又有悠久文化的民族是不會懂的』。

其實並不是只有韓國人這樣搞。

以前曾經看過報導,有很多美國總統都有歐洲國家的皇室血統。甘迺迪啦,柯林頓啦,好像連演電影的雷根都有。

最好是。

如果今年歐巴馬當選,搞不好也能夠扯出歐巴馬有皇室血統,而且還是來自非洲肯亞,他父親那一系。

真是夠了。

(不過這應該是大陸人搞出來的假新聞,把大家呼攏一兩天。我看不到這份報紙新聞,也看不懂韓文,所以不知道是真是假,反正笑笑罵罵就好.......)

2008年7月30日 星期三

Graphic Debugger ( Part V )

Pixel History是使用PIX做Shader Debug的第一個步驟。

首先當然還是先抓一個Frame的資料下來,在Details圖表中切到Render那一頁,可以看到整個Render最後的樣子,在圖片上的某個pixel上按下滑鼠右鍵,選擇"Debug this pixel",Pixel History就顯示在Details圖表中的"Debugger"頁面。


Pixel History給我們的資訊,是這個Pixel從初始顏色一直到最後顏色的變化,包括R,G,B以及Alpha的數值。上面這張圖是一開始的兩個數值變化,第一個是Frame buffer最初的顏色,也可以說是上個Frame留下來的顏色。第二個數值則是Clear Backbuffer之後所得到的顏色。
接著往下看。


第三個階段,顯示了pixel shader的輸出結果,以及計算後的最後Frame buffer顏色。左邊有幾個超連結,點選之後,頁面就會切換成shader debugger。


Shader Debugger的上半部是Shader code,下半部是暫存器的內容。左上角有幾個按鈕,可以讓我們一步一步執行Shader code,同時檢查暫存器內容數值的變化。

2008年7月25日 星期五

Why so serious?

看過電影的就知道我在說哪一部電影。

這句話其實是很恐怖的一句話,想想看,有一個幾近發狂的人,拿著小刀放在你嘴裡,威脅著要幫你劃出一道笑容,還說著:『為什麼這麼嚴肅啊?』

小丑才是『黑暗騎士』的電影主角。

超級英雄的電影一直有個通病,那就是越拍越難看,蜘蛛人是如此,以前的蝙蝠俠是如此,就連老字號的超人都是如此。不過這一回的蝙蝠俠可就不同了,編導演三方面用了很大的心力去塑造一個反派角色,就讓這部續集電影的評價變得很高。小丑變成了主角,蝙蝠俠搶不到觀眾的太多目光。

我想,也許這樣一來,就不會讓這部超級英雄電影,越拍越難看。超級英雄的電影,除了炫麗的聲光效果之外,還是需要人物塑造、故事劇情的。超級英雄在第一集已經塑造過了,第二集開始,就塑造一個一個的反派角色吧!

還記得小丑炸掉醫院的那一幕嗎? 沉睡在心裏深處的瘋狂性格是否被喚醒了? 也許有吧,因為從小丑瘋狂的亂按遙控器,到整個醫院化為灰燼的這一段劇情,居然會引起我心裏的共鳴,隔了兩天,一整段畫面還在腦海裡。

希斯萊傑的詮釋也無可挑剔。有注意到小丑說話時斷斷續續,不時還舔一舔嘴唇嗎? 一開始還無法理解為何小丑有這樣的動作,後來才知道那是臉部有傷痕所造成的。

這部劇情是有人性哲理的,有人探討了很多黑白騎士、小丑的意義、雙面人的硬幣、兩艘炸藥船的社會實驗,甚至還有人討論擺滿了炸藥的兩艘船究竟合不合情理,小丑哪裡來的這麼多人力安排這樣的瘋狂計畫...
我想,這是個商業娛樂片,可以加點人性哲理的思考讓影片有深度,但是它畢竟還是個娛樂片,思考深度點到為止就好,讓觀眾能夠期待下一集有更棒的電影可看,真的,不用太嚴肅。

2008年7月24日 星期四

Graphic Debugger ( Part IV )

我們開始看"A single-frame capture of Direct3D whenever F12 is pressed"所得到的結果。請先回頭看這篇文章


Objects View顯示的是系統內的物件資料,包括物件的位址、格式、大小、型態等等。舉例來說,在這個圖表裡,我們可以看到D3D 貼圖物件所使用記憶體的容量、Pixel格式、寬、高等等的資料。
圖表的最上方有一排下拉式Filter選單,可以將列出的物件過濾。例如,在Type選單選擇D3D 貼圖物件,圖表中列出的就只剩貼圖物件。



Events View中,會顯示所有抓下來的D3D API呼叫,同時提供了呼叫的參數,如果參數是某個D3D物件的話,就會顯示物件的位址。在位址上按下滑鼠右鍵,就可以把這個物件的詳細內容顯示在右邊的Details View中。

Details 顯示的內容,跟物件的型態有關,各式各樣我們需要的資訊,都會鉅細靡遺的顯示出來。

現在,我們先來玩Depth-Stencil Buffer。
第一步當然是跑一個D3D程式,抓一個Frame的資料顯示在PIX中。
接著,在Objects View裡面,用"Usage" Filter將Depth-Stencil Buffer取出來。
在這個D3D 物件上用滑鼠右鍵點選,就會出現類似這樣的Pop-up選單,

選擇這第一個也是唯一一個可選的項目,Depth-Stencil Surface的內容就會顯示在Details View裡面了。

Depth數值,是用白色到黑色的灰階值,來表示0.0 ~ 1.0,紅色框框標記的地方,可以讓我們調整邊界數值,上面這張圖,是我將0.95以下的數值都調整成白色得到的結果。

左下的Events View跟Details View可以合併一起來看,我們在Events裡面選擇一個一個的Events,可以看見當時的Depth Surface內容,換句話說,我們可以對Depth Surface做Tracing!!

其他的各種D3D物件,使用方式都類似,只是在Details裡面的內容不同。

下一回,我們來介紹一下也很好玩的Pixel History。

2008年7月18日 星期五

隱身在幕後的Singleton

今天看到一個很好玩的架構,我稱之為「隱身在幕後的Singleton」。

我們有一個Symbol類別,物件放在Symbol Table中,這個Symbol Table是一個Singleton。


class CSymbol
{
public:
  // constructor, destructor
  CSymbol( char const* pStr );
protected:
  // Initializes the symbol table
  static void InitializeTable();
  // returns the current symbol table
  static CSymbolTable* GetTable();
  // The standard global symbol table
  static CSymbolTable* s_pSymbolTable;
  friend class CCleanupSymbolTable;
};


class CCleanupSymbolTable
{
public:
  ~CCleanupSymbolTable();
};


class CSymbolTable
{
public:
  CSymbolTable();
  ~CSymbolTable();
};

SymbolTable 是放在 Symbol 類別裡的一個靜態成員資料,所以,所有的 Symbol 都共用相同一個。
一開始這個 Table 是不存在的,在 Symbol 的建構子裡面,會呼叫 GetTable() 函式, 這個函式會new 一個 Table 出來,如果沒有的話。
也就是,第一次建立 Symbol 物件時,就會自動地建立 Symbol Table 。

CleanupSymbolTable 物件只有定義一個解構子,它的 code 是這樣:

CCleanupSymbolTable::~CCleanupSymbolTable()
{
  if (CSymbol::s_pSymbolTable) delete CSymbol::s_pSymbolTable;
  CSymbol::s_pSymbolTable = 0;
}


所以這個物件的用處沒別的,就是在解構子裡面 delete 掉 Symbol Table Singleton。
然後我們再宣告一個靜態物件變數。

static CCleanupSymbolTable g_CleanupSymbolTable;

這樣,當程式結束的時候,程式會清除靜態變數 g_CleanupSymbolTable,而這個變數被清除時,會 delete 掉 Symbol Table。 所以這個 Symbol Table 就像是隱形了一樣,不需要外部呼叫new / delete,用到它的時候,自然會 new 出來,程式結束會自動 delete 掉。

完全的全自動操作。

2008年7月17日 星期四

Graphic Debugger ( Part III )

接下去寫PIX其他的圖表之前,先讓我偷懶一次,寫一個很小卻很炫的功能。

這功能叫做抬頭顯示器,Heads-Up Display (HUD)。


HUD的設定就在每個Frame統計數據的選項後方,把這個項目打勾之後,Time line的數據線圖,就會即時的顯現在所要抓取數據的視窗中。


透過這樣的數據顯示,我們可以觀察即時的數據變化,對效能的分析也有很大的幫助。

不過PIX的這項功能在版本比較舊的DirectX SDK中並沒有提供,所以,如果你的PIX中沒看到這項功能,就更新一下SDK的版本吧...

2008年7月16日 星期三

Graphic Debugger ( Part II )

現在我們可以開始來看PIX的測試結果。
首先是Time line圖表。


Time line圖表有四個部分,灰色的Bar是CPU 負載圖,第二條Bar是GPU 負載圖(在Vista作業系統下才有這條Bar,XP是沒有的),底下的線圖會顯示每個Frame D3D 呼叫所統計出來的數值,最下方有四個下拉式選單,可以選擇在線圖上所要顯示的數值。選單右邊有Zoom in, Zoom out的按鈕,可以調整時間比例。

CPU 的負載Bar用黑色邊框圍起來的灰色長方形表示一個Frame,上面這張圖裡面,在左邊的箭頭處,我們看到一個花了很長時間的Frame,通常這是初始化的階段會有的現象,中間的箭頭,我們看見幾個分佈很平均的方塊,時間也不長,負載還算不錯,右方的箭頭所指的,是一條比較粗的黑線,這表示這個Frame的時間非常短。另外,在初始化的Frame之後,有一小段空隙,這段空隙表示CPU在這時候是空閒的。

GPU的負載Bar稍為複雜些。黑色邊框裡面的長方形會有三種顏色,藍色表示GPU正在執行所交付的工作,灰色表示GPU在idle狀態,等待CPU交代工作,如果出現紅色,就表示某些GPU執行工作所需要的資源被鎖住,以致GPU必須等待資源被釋放出來。

這兩條Bar最主要的用途在於效能分析,從線圖裡我們可以查看到CPU與GPU的相對負載狀況。


這裡我們看到一個狀況,CPU是持續負載的,而GPU負載則斷斷續續的,有不少的空閒時間。所以如果我們能夠找到一些工作,從CPU運算轉到GPU運算上的話,整體的效能就會上升。

至於數值統計線圖的部分,主要的功用在檢查是否有不尋常的數值變化,還有就是查看每個Frame的D3D API的呼叫次數、資源使用量等等的數值是否合理。這些都可以很簡單的從線圖上看出來,所以也不用多做什麼解釋。

Time line線圖的說明就到這邊,後面還有更好玩的數據資料圖表。

2008年7月10日 星期四

這個遊戲會吸金

這是個網路版的棒球休閒遊戲 -- プロ野球チームをつくろう!ONLINE

銀狐兄有一系列的介紹

簡單來說,每個玩家在這遊戲中會擁有一支職棒球隊,每十六個球隊會組成一個聯盟互相比賽。遊戲伺服器每隔一個半小時會進行一場比賽,每天進行十二場。玩家所要做的事就是安排球員陣容,調整先發、板凳、一軍、二軍等等。
球隊的球員呢,是用抽卡片的方式取得,聯盟的每場比賽玩家都可以獲得一些積點,這些積點就是抽卡片的本錢。

本來,我是玩得很愉快的,每天上線看一下戰績,抽一下卡片,抽到好球員就換一下先發陣容。很愉快,而且不用花任何一毛錢。

但是就在前兩天,愉快的抽卡片的時候,突然間畫面一閃,一張傳說中的卡片出現 -- 野茂英雄!!

然後我就陷入天人交戰了......

像野茂英雄這樣的傳奇球員,玩家是不能隨隨便便就把他放上一軍球員的名單中的,必須擁有傳奇球員的使用權,而這個使用權是必須玩個轉輪的遊戲來抽籤取得的。問題就在,轉輪遊戲要花錢,像轉蛋一樣的投一次幣玩一次,而且,還不保證一定會抽到這個使用權。

我可以不管它,就用其他的球員玩玩就算了,反正不過就是個遊戲。可是這是野茂英雄,小時候還學過他的投球姿勢玩棒球的野茂英雄。

於是我就淪陷了.......

為了不讓我的野茂英雄在二軍鬱鬱以終,我開始投幣玩轉輪,偏偏玩轉輪的手氣很糟糕,不想要的獎品拿了一堆,就是抽不到使用權。最後,就在準備放棄的前一刻--每次都這樣--使用權到手了。

算一算,一個野茂英雄在一個晚上就吸了我好幾千日幣..........

2008年7月9日 星期三

越來越糟糕的Spider Man

Spider Man第三集開始在電影頻道上播出了。從第一集拍到第三集,娛樂效果依舊,越來越糟糕的是它的故事劇本。

第一集的故事是中規中矩的超級英雄的故事,一個超級英雄跟一個超級壞蛋,再加上一個一定會被發現關係而陷入危機的女友,套入到百看不厭的超級英雄公式裡,就完成了一個很棒的超級英雄電影。

第二集的故事其實是比較有點內涵的,英雄、壞蛋、女友的公式都還在,另外又加了一點超級英雄在英雄與凡人之間分身乏術的兩難困境。老實說,若不是電影結束前五分鐘的那一段敗筆,我會很喜歡這樣的超級英雄故事。

這部電影到了最後,瑪莉珍終於發現蜘蛛人的真實身分,而蜘蛛人也終於了解"忠孝不能兩全"--英雄與女友不可兼得--的既成事實,於是在高空的蜘蛛網上,彼得帕克目送瑪莉珍隨著未婚夫離開。

The End!!!!!

這部電影到這裡就應該結束了!!! 多加五分鐘的瑪莉珍逃婚,回到彼得帕克身邊的劇情做什麼?? 來這麼一段Happy Ending的敗筆做什麼??

前面鋪陳了一百分鐘的兩難困境,到了最後五分鐘完全消失,這是哪個蠢蛋的主意??

第三集的故事就更爛了。

三 個超級壞蛋,其中一個還從壞人變好人,再變壞人,然後又瞬間變成另一個超級英雄。多了一個無關痛癢的花瓶角色,有沒有她對劇情發展毫無影響,只不過稍微替 代一下瑪莉珍的危險處境。沙人的特效做得不錯,但是硬把沙人扯到跟班帕克的死有關,讓彼得帕克有變壞的機會,就是另一個爛到不行的設定。結果最後這個沙人 居然還改過向善,成為一陣風飛走,又搞了個奇怪的Happy Ending。

照我說,第三集的超級壞蛋只要一個小綠惡魔就夠了。哈利奧斯朋與彼得帕克之間的愛恨情仇,再多一個瑪莉珍來發展三角關係的劇情,還怕故事不夠好麼?

整部電影,娛樂效果還是很不錯,就是這故事劇情,完全無腦,搞得我不得不寫這一篇來發發牢騷....

2008年7月8日 星期二

Graphic Debugger ( Part I )

這幾天在玩DirectX SDK中的一個工具程式,PIX。

PIX有幾個主要的用途:效能分析、資源使用分析、以及 Graphic Debugger。


第一個選項"Statistics for each frame, using counterset"的主要用途是做效能分析。PIX會統計每個Frame D3D Call的數量,例如:DrawPrimitive, SetRenderState, Buffer lock/unlock 等等。

第二個選項"A single-frame capture of Direct3D whenever F12 is pressed",則是當我們按下F12時,PIX就會將這個Frame的所有D3D call記錄下來,而且是鉅細靡遺,等會兒說了就知道。

簡單的操作步驟,
1. 最上面的Program Path先選擇所要測試的程式。
2. 兩個選項擇一。
3. 按下右下角的"Start Experiment",所要測試的程式就會執行起來。
4. 執行結束後,PIX會給我們一個資料畫面。

選擇"Statistics for each frame, using counterset"會得到類似這樣的圖表

最上面的一個圖表是"Time line",也是每個frame資料統計顯示的地方。中間"Objects"圖表的和右下的"Details"圖表在這個統計資料裡是空的。左下的圖表是"Events",這裡會將每個Frame的統計資料數值列出來。

如果選擇的是"A single-frame capture of Direct3D whenever F12 is pressed",就會得到底下這樣的圖表

在這個測試裡,Time line沒什麼用處,因為只是一個frame的結果。但其他的三個圖表用處就非常大了。所謂的鉅細靡遺,就是指這三個圖表給我們的資訊。

這些圖表怎麼用?

我們下次再說.....

2008年7月4日 星期五

組織起一個遊戲引擎

在組織一個遊戲引擎之前,第一件也是最重要的一件事是,先定義這個遊戲引擎的定位是什麼。

舉例來說,這個遊戲引擎將會是一個繪圖程式庫還是一個全能的遊戲開發環境?

像Gamebryo、RenderWare是一個繪圖程式庫,Unreal就是一個很強大的,幾近全能的遊戲開發環境。甚至還有像BigWorld這樣的專門為大型網路遊戲所設計的遊戲引擎。

定位的另一種涵義是需求。我常常犯一種錯誤,該處理的需求不做,卻偏偏做一堆用不到的東西。

我把這個遊戲引擎,定位為一個繪圖程式庫,提供遊戲需要的基本的繪圖處理功能。另外,我會再加上必要的工具程式。

說實話,就使用者的觀點來說,工具程式比程式庫還重要。但是對開發者而言,尤其是技術導向的開發者,就覺得那是枝微末節的事。我曾經忽略過這樣的事實,後來就必須老老實實的還債。

範例程式跟說明文件也很重要,不過在開發的過程中,我會寫需要的設計文件與測試程式,也就可以滿足這兩塊的需求。

簡單的組織架構像是這樣。

以Graphic Kernel為核心,Math Library、Core Utility提供必要的支援物件,Tools Set則是工具程式組。

比較特殊的是Graphic API與Graphic Kernel 之間的關係,我用了反向依存的方式來降低兩個模組之間的耦合程度。Graphic Kernel中定義了一個IGraphicAPI的介面,而實做層則放在Graphic API模組中。用這樣的方式,我把最低階的繪圖工作拉到Graphic API模組來做,這個模組會跟DirectX API有關聯,而Graphic Kernel模組則完全不受DirectX影響。

當然,野心如果大一點,我可以做兩三個不同實做程序的Graphic API模組,這樣我只要將API模組抽換,我的程式就能夠支援DirectX, OpenGL,.....

不過野心太大不是好事。

基礎的組織結構就這樣了,我想我可能還需要針對模組內的架構來寫一些設計文件。

2008年7月2日 星期三

好嫩的 Mulder 與 Scully

昨天晚上開始,X Files開始重播了,從第一季開始。於是就看到很年輕的Mulder與Scully,還有煙還沒抽很兇的Cancer Man。

經典,好懷念。

第一集的劇情就很有X Files的味道,只是沒想到的是,Scully居然第一集就寬衣解帶了。

劇情是這樣,兩人到一個鄉下地方去查案。這地方的樹林裡連續發生幾個奇怪的命案,死者身上沒傷痕,就是腰背附近有兩個紅點。這兩個紅點成因不明,疑似是外星人留下的記號。

劇情帶著帶著,就帶到Scully寬衣梳洗,卻發現身上也有兩個紅點,嚇得她趕緊披上睡衣衝到Mulder房裡,然後又寬衣了一次,讓Mulder看看......(結果是蚊子咬的.....Scully不是學醫的嗎? 蚊子咬的也不知道?)

好,這不是重點。

接下來的劇情,就是Mulder跟Scully聊天,開始講Mulder的妹妹疑似被外星人抓走,Mulder在X File部門想找外星人,還有美國政府的陰謀等等。沒幾分鐘的劇情,卻是後面一大堆劇情的基礎背景設定。

所以說,後面很多看起來亂扯的劇情,像是Mulder有事沒事為了妹妹歇斯底里、深喉嚨有事沒事就會報一個美國政府陰謀的明牌等等,其實都是有所本的。絕對不是編劇江郎才盡在亂掰。

只是,當初第一次看的時候,誰還會記得這兩分鐘在講什麼啊?

尤其是Scully還寬衣了兩次....

好,我知道這不是重點....