「所謂職業選手是指能夠得到比外界期待更好的成績,不然的話,我要怎麼離開自己生長的故鄉呢?我想要去遠方。」
Friday, January 6, 2012
我想要去遠方
「所謂職業選手是指能夠得到比外界期待更好的成績,不然的話,我要怎麼離開自己生長的故鄉呢?我想要去遠方。」
Friday, April 29, 2011
NPAPI & anothor single triangle

於是,我發現了一個長久以來我都視為理所當然,可是一直忽略的事實,那就是瀏覽器應該可以用native code寫plugin吧...flash,quick time,甚至Unity3D引擎,quake live這些技術,看起來不可能是用script寫出來的。
於是我用google查了web browser native plugin或類似的東西,結果就掉出了google html5 native code計畫,html 5大業的確很有潛力,sand box的環境也可能提供比較好的安全性,不過native code計畫看起來還不太成熟,目前只有gcc的環境,而我是個用visual studio的軟派程式員,只好放棄這個方向。不過flash,或unity引擎,都是在html 5的native code計畫出現前就有的東西,顯然有其他的方式可以達成,經過一堆亂七八糟的關鍵字搜尋,終於找到了關鍵字是甚麼---NPAPI和ActiveX。
NPAPI是給非IE用的瀏覽器plugin API(Firefox,Chrome等等),ActiveX就是...恩,微軟的IE。這兩個API,都可以讓我們在瀏覽器中,用C/C++寫plugin。另外這也是為甚麼plugin都分IE和非IE兩種...
有關NPAPI的資訊,其實在網路上還滿少的,官方文件和這個blog,我覺得算是比較好的資源。其中那位blog的作者,開發了FireBreath這套可以跨NPAPI和ActiveX的plugin API。另外在codeproject上有一個範例。
因為我只想用OpenGL畫一個三角形,於是我下載了codeproject上的範例修改了一下,把有關scriptable的部分全部拿掉,然後就畫了一個三角形。
真的有興趣的人,可以用svn checkout http://ianjoker.googlecode.com/svn/trunk/npgl下載source code。
稍微紀錄一下NPAPI的設計,首先,他是"真正"的plugin設計,compile好的NPAPI plugin是一個動態函示庫(.dll或.so),而且,這個plugin理論上可以給FireFox,Chrome,Safari或任何支援NPAPI的瀏覽器使用,而不用重新compile或link任何東西。這與一些不太plugin架構的plugin很不一樣,例如Ogre引擎中的RenderSystem或SceneManager等plugin,只要OgreMain有改變重新compile,這些plugin就必須重新compile或link OgreMain.lib,否則不保證plugin可以用。
可是NPAPI plugin不用重新link卻可以給各個瀏覽器(還包括不同版本,不同compiler等)使用,這是怎麼辦到的呢?好吧,原因很簡單,因為一開始就根本不用link任何.lib。
NPAPI靠的,是用C語言的ABI(Application binary interface)非常統一的特性,幾乎所有的interface都使用C語言制定,其中有三個C的inteface是瀏覽器與plugin的接口。
NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs);
NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs);
NPError OSCALL NP_Shutdown();
C的interface,可以利用GetProcAddress(windows)或dlsym(Linux)來取得位址。因此瀏覽器不用去link任何plugin的lib就可以呼叫這三個function。這當然是任何plugin設計的基礎,但是還缺了一半,如果plugin不link瀏覽器的.lib,那plugin就無法呼叫任何瀏覽器本身的function,瀏覽器無法提供任何服務給plugin使用!
解決方案很簡單,NP_Initialize這個function會在plugin被瀏覽器載入時呼叫,這時候會傳進來一個NPnetscapeFuncs,這其實是一個function pointer的table,裡面每個function pointer就是瀏覽器提供給plugin呼叫的function,例如我想跟瀏覽器alloc一塊記憶體,我可以呼叫NPnetscapeFuncs::memalloc。因此plugin不用link瀏覽器的.lib,link這件事情,是在runtime執行NP_Initialize的時候做的。
反向的則是NP_GetEntryPoints會需要我們填function pointer進NPPluginFuncs這個function pointer table,這些function pointers是plugin提供給瀏覽器呼叫的callback,例如當瀏覽器需要new一個新的plugin的instance的時候,瀏覽器會呼叫NPPluginFuncs::newp這個callback,我們必須實做這些function,然後把他們填入NPPluginFuncs交給瀏覽器。
因為我想做的是利用OpenGL畫三角形,想要OpenGL就必須要有window handle,而NPPluginFuncs正好有提供setwindow這個callback,會在瀏覽器建plugin window的時候呼叫,瀏覽器呼叫這個callback的時候,會傳進一個NPWindow struct,這個struct可以拿到window handle!任何一個graphics programmer,只要能拿到window handle就可以解決一切難題!!!
當然,事情永遠不會這麼簡單的...
首先是API的header問題,雖然說理論上這是一個跨瀏覽器的API,包含了npapi.h,npfunctions.h,npruntime.h,nptypes.h四個檔案,不過只要有人的地方,就有紛爭,更不用說瀏覽器這種兵家必爭之地了。我在demo中放了Mozilla的官方SDK版本。我試過在FireFox 3.x或4.x都是ok的,不過很可惜的是Chrome似乎不能用。Google他們自己可能也看到了這個問題,因此他們maintain了一份號稱可以跨平台的header,可惜的是我試過似乎在FireFox下會當掉。我還沒有仔細檢查哪裡出了問題,不過如果真的要寫跨平台的plugin,說不定比較好的方式還是去用FireBreath那套API比較好,否則要自己去處理一些跨瀏覽器的問題。
另外是plugin安裝的方式,按照Mozilla官方文件說法,在windows平台上要去registry註冊一些機碼好讓瀏覽器可以認得plugin放的地方,application的MIMEType,附檔名等資訊等等。不過我試了老半天沒辦法work,去看了codeproject的demo做法是直接用.rc檔內嵌在編譯出來的.dll中了,然後必須把編譯好的.dll丟到(FireFox安裝資料夾)\plugins\這個資料夾下面,如果沒有這個資料夾就自己建一個。當然這好像不是理想的做法,因為plugin無法安裝到我們自己想安裝的地方。另外還有個小地方也很奇怪,那個.rc檔裡面有個語言的選項,因為我的VC是中文版的,所以他預設都設成中文,可是中文的plugin無法用,一定要改成英文才行,這裡也是完全不知所以然
最後,因為plugin畫面更新是lazy的方式,瀏覽器覺得需要更新那個window才會有windows message重畫那個window,當然這樣做無法做real time的遊戲,如果要自己控制更新window,只好自己開另一個thread來建OpenGL context。總之,這只是implementation detail,好讓我可以得到60 FPS的triangle。60 FPS就是比較帥(自high)~
結論是,雖然這不是甚麼很難的技術,不過感覺網路上資源還滿少的,如果真的想要把這鬼東西放進工具,可能很多小細節都會讓實作的人很痛苦吧,而且那個痛苦的人看起來就是我啊...
Saturday, March 19, 2011
麥田捕手
"I Thought what I'd do was, I'd pretend I was one of those deaf-mutes."
"一個不成熟的人的特徵,是他願意為某種信念英勇的死去;一個成熟的人的特徵,是他願意為某種信念謙卑地活著。"
看了攻殼機動隊,所以去找了這本名著來看。
Tuesday, February 15, 2011
OpenGL extensions & code generator
To get extensions work on different platforms often means various mechanisms to get the extensions' function pointer, deal with different calling conventions, etc.
The easiest way to deal with such mess is use a library like GLEW and forget about it. But sometimes when I code my own little stuff, I only use a very small set of extensions(often times I just want to test the extensions functionality) , GLEW's mega-header is often very browse/search unfriendly, and if the GLEW's version is out of date, I have to download it again.
I used to code every single extension manually, and it's really boring and repeated work. I don't know if there exist an automatic extensions generator(I know it exist, most extensions lib is generated by such generator, I just have to find an excuse to make my own), give it a file which contain the function definition, and it output the .h and .cpp. Then I put the two files in my project and voila.
I think this is an interesting little project and recently I have been learning Python. So I give it a try using Python.
The gl extension source file looks like this
[core]
void glEnable (GLenum capability)
void glDisable (GLenum capability)
void glBlendFunc (GLenum sfactor, GLenum dfactor)
...
[GL_EXT_texture_compression_s3tc]
...
The generator read each line of the file, then using Python's regular expression module re to parse the line to see if it's an [...], which means a group of extensions. [core] group is special, which contains functions in core GL spec . Other [...] must contains it's extension's name string. And if the line is parsed as function declaration, it is split into three pieces - return type, function name and args list, then it's stored in a Python dictionary using function name as key for latter use.
When parse complete, the generator output .h and .cpp. The .h look like this(with a lot of hassle omitted),
//core
extern void(JGL_API_ENTRY jglEnable) (GLenum capability);
extern void(JGL_API_ENTRY jglDisable) (GLenum capability);
extern void(JGL_API_ENTRY jglBlendFunc) (GLenum sfactor, GLenum dfactor);
...
//GL_EXT_texture_compression_s3tc
...
namespace joker
{
struct glCaps{
bool support_core;
bool support_GL_EXT_texture_compression_s3tc;
};
void InitGL(glCaps** caps);
}
then in my project, I just call InitGL(&caps), init the extensions and get the caps, if the extension is supported, I can call it's jglXXX function.
the generator is halfway done, the caps check is not implemented yet, and I also want to add log version of gl functions. And it only support Mac/Windows.
The source can be found here. and the extension def file here.
Yeah, many stuff looks like Quake 3's qgl, because I steal most ideas from it :) .
And of course this is only a toy, any production code should use GLEW instead.
P.S. Now I am really confused, what's the difference between core/extension? OpenGL sucks...
Monday, December 27, 2010
OpenCL Wave & MacOS

Just port the whole thing to Mac OS 10.6. Spent about two nights, mainly dealt with platform specific OpenCL/OpenGL share context issue. Maybe I should start add some lighting to the ocean.
//can I write code now?
void main(){
printf("hellow blogger\n");
}
Wednesday, December 22, 2010
siggraph 2010 asia
first day
飛行時間非常短,短到連一部電影都看不完(其實真正原因是因為他一直插播...),到韓國時,從窗外灑進來金黃色的陽光,會讓人誤以為外面是個晴朗炎熱的天氣,不過一出了飛機艙,馬上就會發現這完全是個假象,從登機門細縫吹進來的冷風非常的冷。
出關後到科南找到的租借手機的地方借了iphone,理論上應該五天免費,不過實際上應該一不小心就會付出額外費用吧,因為只有wifi免費,3G就要收錢,另外,在旅館wifi的收訊非常糟,幾乎收不到訊號,因此租那隻iphone還沒有任何實際效用。旅館的網路費用很高,wifi品質也不好,韓國號稱世界網路最快應該是誇大其詞吧。
旅館房間是單人房還加一張床,打掃的不太乾淨,還有前房客的頭髮,據Brian說他們房間還有用過的保險套...然後牙刷牙膏都要賣錢,實在很難讓人有好印象...
晚上大家走了一段路(真的超級冷...)去吃一家韓國烤肉,因為菜單完全沒有圖片,也沒人會韓文,所以就讓老闆娘幫我們配菜,一人一萬韓元。跟台灣吃的烤肉還滿不一樣的,肉是一大片一大片沒有醃過的,烤盤是長方形的一大塊鐵盤,然後斜斜的放著讓他可以從缺口滴油。肉要用剪刀剪成小小片,然後加一堆的佐料沾醬一起烤,烤好後用生菜包起來吃,另外還有一些泡菜,小菜(生的蚵仔只有獸王敢吃)和辣的豆腐鍋等配菜。吃起來還算ok。臨走前老板娘送了一人一個橘子。
回程去了一家便利商店買東西(越來越冷了...),韓國的便利商店似乎不像台灣幾乎都是seven或全家連鎖,而是有很多種不同的小店,買了一包類似蝦味先的零食,和一瓶20%酒精濃度的燒酒,目前在旅館大約喝了三分之二瓶的狀態下寫東西,有點恍神,應該是這輩子一次喝下最多酒精吧,喝酒真的是很好的取暖方式啊,可惜那個燒酒不好喝,味道很像直接在喝酒精,還有點擔心是不是買到工業酒精了。
開始酒醉了,剛打給Brian居然忘了他名字,好像某人犯過的錯啊...哈哈哈
second day
今天是研討會第一天,所以必須早點起床去會場登錄,大概六點就起床了吧,出旅館的瞬間,真的是讓想罵髒話的冷,據AccuWeather顯示,應該是零下11度,這樣的天氣,我們用走路的到Coex展覽館,幸好有買手套和帽子...。
會場的標示很差,我們從coex北邊的大門進去,有看到小小的一張siggraph asia海報,但都沒有標示方向,Brian還遇到了他大學同學也來參加,可是他同學也不知道登錄的地方在哪,結果再會場繞了老半天,問了其他來沒關係的展覽的人員,最後發現是要走到會場的南邊。
上的第一堂course是叫multi-dimensional spatial sorting的課程,講師是一個老美教授,內容大約就是一些quad tree,AABB tree之類的和一些那個教授提出來的改善方法,當然這些課程內容都收錄在會場也有賣的,他出的spatial sorting書裡面。
因為那個教授有些demo是放在網頁上的,所以他從上課前就一直試著要連無線網路,可是訊號很差一直斷網,他看起來還滿生氣的一直說this is ridicules,unacceptable,後來有個工讀生之類的人拿了一條網路線進來,結果也沒用。我們一般的參加者,如果要用會場網路居然還要付錢,韓國的網路真的很好嗎?並不是家裡網路很快就是網路很好吧?
另外有些研討室真的很小,最小的大概只有二十個位子,韓國人好像不把這個當作國際研討會是吧,下一堂課在同一個教室,是有關mocap的課程,結果我去上個廁所回來那間教室就被擠爆了,只好去聽pixar的toy story 3一些lighting設定之類的東西,老實說有點失望,因為投影片和demo影片的影像品質很差,細節都看不清楚了,另外講師有一個是韓國人,所以他用英文講可是不太能表達他的意思,總之內容大約是一些lighting和情境之間的關係,不過我想大部份有經驗的美術應該都很清楚這些內容了。
第一天的會議,這個研討會讓我留下一些不太好的第一印象...