2012年9月13日 星期四

An intro to modern OpenGL

一個介紹OpenGL的地方
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-1:-The-Graphics-Pipeline.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2:-Hello-World:-The-Slideshow.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2.1:-Buffers-and-Textures.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2.2:-Shaders.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-2.3:-Rendering.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-3:-3D-transformation-and-projection.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-4:-Rendering-a-Dynamic-3D-Scene-with-Phong-Shading.html

著色器 (Shader)
http://cg2010studio.wordpress.com/2011/06/29/shader/
幾何著色器 (Geometry Shader)
http://cg2010studio.wordpress.com/2011/06/30/geometry-shader/
Vertex and Fragment Pipeline
http://cg2010studio.wordpress.com/2011/08/02/vertex-and-fragment-pipeline/

Vertex Shader 结构
http://dev.gameres.com/Program/Visual/3D/VertexShader.htm
OpenGL 3.x教學: 第1章: Shader Based OpenGL
http://viml.nchc.org.tw/blog/paper_info.php?CLASS_ID=1&SUB_ID=1&PAPER_ID=167
3D繪圖(3D Graphics Pipeline)
http://www.ategpu.com/2009/06/04/3d%E7%B9%AA%E5%9C%963d-graphics-pipeline.html

OpenGL Development on Linux - Tutorial
http://ogldev.atspace.co.uk/index.html

如果在ubuntu裏build code時發生 "error: GL/glut.h: No such file or directory"
試看看安裝apt-get install freeglut3-dev

發生"warning: GL/glew.h: No such file or directory"
試看看安裝apt-get install libglew1.5-dev

https://github.com/CIS565-Spring-2012/cis565-spring-2012.github.com
http://http.developer.nvidia.com/GPUGems/gpugems_copyrightpg.html

http://www.youtube.com/watch?v=98SSgxDe-5A

The Linux Graphics Stack
http://blog.mecheye.net/2012/06/the-linux-graphics-stack/

2012年9月1日 星期六

John Carmack密码:0x5f3759df


John Carmack密码:0x5f3759df
Quake-III Arena (雷神之锤3)是90年代的经典游戏之一。该系列的游戏不但画面和内容不错,而且即使计算机配置低,也能极其流畅地运行。这要归功于它3D引擎的开发者约翰-卡马克(John Carmack)。事实上早在90年代初DOS时代,只要能在PC上搞个小动画都能让人惊叹一番的时候,John Carmack就推出了石破天惊的Castle Wolfstein, 然后再接再厉,doom, doomII, Quake…每次都把3-D技术推到极致。他的3D引擎代码资极度高效,几乎是在压榨PC机的每条运算指令。当初MS的Direct3D也得听取他的意见,修改了不少API。

最近,QUAKE的开发商ID SOFTWARE遵守GPL协议,公开了QUAKE-III的原代码,让世人有幸目睹Carmack传奇的3D引擎的原码。

这是QUAKE-III原代码的下载地址:http://www.fileshack.com/file.x?fid=7547

我们知道,越底层的函数,调用越频繁。3D引擎归根到底还是数学运算。那么找到最底层的数学运算函数(在game/code/q_math.c),必然是精心编写的。里面有很多有趣的函数,很多都令人惊奇,估计我们几年时间都学不完。

在game/code/q_math.c里发现了这样一段代码。它的作用是将一个数开平方并取倒,经测试这段代码比(float)(1.0/sqrt(x))快4倍:

float Q_rsqrt( float number )
{
   long i;
   float x2, y;
   const float threehalfs = 1.5F;
   x2 = number * 0.5F;
   y   = number;
   i   = * ( long * ) &y;   // evil floating point bit level hacking
   i   = 0x5f3759df – ( i >> 1 ); // what the fuck?
   y   = * ( float * ) &i;
   y   = y * ( threehalfs – ( x2 * y * y ) ); // 1st iteration
   // y   = y * ( threehalfs – ( x2 * y * y ) ); // 2nd iteration, this can be removed

   #ifndef Q3_VM
   #ifdef __linux__
     assert( !isnan(y) ); // bk010122 – FPE?
   #endif
   #endif
   return y;
}

函数返回1/sqrt(x),这个函数在图像处理中比sqrt(x)更有用。
注意到这个函数只用了一次叠代!(其实就是根本没用叠代,直接运算)。编译,实验,这个函数不仅工作的很好,而且比标准的sqrt()函数快4倍!要知道,编译器自带的函数,可是经过严格仔细的汇编优化的啊!

这个简洁的函数,最核心,也是最让人费解的,就是标注了“what the ***?”的一句
      i   = 0x5f3759df – ( i >> 1 );
再加上y   = y * ( threehalfs – ( x2 * y * y ) );
两句话就完成了开方运算!而且注意到,核心那句是定点移位运算,速度极快!特别在很多没有乘法指令的RISC结构CPU上,这样做是极其高效的。

算法的原理其实不复杂,就是牛顿迭代法,用x-f(x)/f’(x)来不断的逼近f(x)=a的根。
简单来说比如求平方根,f(x)=x^2=a ,f’(x)= 2*x,f(x)/f’(x)=x/2,把f(x)代入
x-f(x)/f’(x)后有(x+a/x)/2,现在我们选a=5,选一个猜测值比如2,
那么我们可以这么算
5/2 = 2.5; (2.5+2)/2 = 2.25; 5/2.25 = xxx; (2.25+xxx)/2 = xxxx …
这样反复迭代下去,结果必定收敛于sqrt(5),没错,一般的求平方根都是这么算的
但是卡马克(quake3作者)真正牛B的地方是他选择了一个神秘的常数0x5f3759df 来计算那个猜测值
就是我们加注释的那一行,那一行算出的值非常接近1/sqrt(n),这样我们只需要2次牛顿迭代就可以达到我们所需要的精度.

好吧 如果这个还不算NB,接着看:

普渡大学的数学家Chris Lomont看了以后觉得有趣,决定要研究一下卡马克弄出来的
这个猜测值有什么奥秘。Lomont也是个牛人,在精心研究之后从理论上也推导出一个
最佳猜测值,和卡马克的数字非常接近, 0x5f37642f。卡马克真牛,他是外星人吗?
传奇并没有在这里结束。Lomont计算出结果以后非常满意,于是拿自己计算出的起始
值和卡马克的神秘数字做比赛,看看谁的数字能够更快更精确的求得平方根。结果是
卡马克赢了… 谁也不知道卡马克是怎么找到这个数字的。
最后Lomont怒了,采用暴力方法一个数字一个数字试过来,终于找到一个比卡马克数
字要好上那么一丁点的数字,虽然实际上这两个数字所产生的结果非常近似,这个暴
力得出的数字是0x5f375a86。

Lomont为此写下一篇论文,”Fast Inverse Square Root”。

=======================================================
SquareRootFloat函数最关键的一句就是 i=0x5f3759df-(i>>1);
以下是对它的部分解释:

牛顿迭代法最关键的地方在于估计第一个近似根。如果该近似根与真根足够靠近的话,那么只需要少数几次迭代,就可以得到满意的解。

接着,我们要设法估计第一个近似根。这也是上面的函数最神奇的地方。它通过某种方法算出了一个与真根非常接近的近似根,因此它只需要使用一次迭代过程就获得了较满意的解。它是怎样做到的呢?所有的奥妙就在于这一行:

i = 0x5f3759df – (i >> 1);         // 计算第一个近似根
超级莫名其妙的语句,不是吗?但仔细想一下的话,还是可以理解的:float类型的数据在32位系统上是这样表示的。

bits:31 30 … 0
31:符号位
30-23:共8位,保存指数(E)
22-0:共23位,保存尾数(M)
所以,32位的浮点数用十进制实数表示就是:M*2^E。开根然后倒数就是:M^(-1/2)*2^(-E/2)。现在就十分清晰了。语句 i>>1其工作就是将指数除以2,实现2^(E/2)的部分。而前面用一个常数减去它,目的就是得到M^(1/2)同时反转所有指数的符号。

============================================

参考:
最后,给出最精简的1/sqrt()函数:

float InvSqrt(float x)
{
   float xhalf = 0.5f*x;
   int i = *(int*)&x; // get bits for floating VALUE
   i = 0x5f375a86- (i>>1); // gives initial guess y0
   x = *(float*)&i; // convert bits BACKto float
   x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
   return x;
}

PS. 这个 之所以重要,是因为求 开根号倒数 这个动作在 3D 运算 (向量运算的部份) 里面常常会用到,如果你用最原始的 sqrt() 然后再倒数的话,速度比上面的这个版本大概慢了四倍吧… XD

資料來源:

2012年8月25日 星期六

人生的價值

【人生的價值】
小和尚問師父:
「師父,我人生最大的價值是什麼呢?」

老和尚說:
「你搬一塊大石頭,拿到山下菜市場上去賣,假如有人問你什麼價錢,你不要講話,只伸出一個指頭;假如他跟你還價,你不要賣,然後馬上抱回來,師父就告訴你,你人生最大的價值是什麼。」

第一天一早,小和尚抱了石頭,興致勃勃地跑到山下菜市場上去賣。

菜市場上人來人往,人們很好奇,誰會買一塊石頭呢?

一會兒,一個家庭主婦走了過來,問小和尚:
「這石頭多少錢賣呀?」

小和尚伸出了一個指頭,那個家庭主婦說:
「10塊錢?」

小和尚搖搖頭,家庭主婦說:
「那麼是100塊錢?好吧,好吧!我剛好拿回去壓酸菜。」

小和尚聽到:「我的媽呀,一文不值的石頭居然有人出100元錢來買!我們山上有的是呢!」

於是,小和尚遵照師父的囑託沒有賣,樂不可支地抱回山上,去見師父:
「師父,今天有一個家庭主婦願意出100元,買我的石頭。師父,您現在可以告訴我,我人生最大的價值是什麼了嗎?」

老和尚說:
「嗯!不急,你明天一早,再把這塊石頭拿到博物館門口去,如果他還價,你不要賣,再抱回來,我們再談。」

第二天早上,小和尚又興高采烈地抱著這塊大石頭,來到了博物館。

在博物館外,一群好奇的人圍觀,竊竊私語:
「一塊普通的石頭,到底有什麼價值,難不成是什麼稀奇呢?只是我們還不知道而已。」

這時,有一個人對小和尚大聲說:
「小和尚,你這塊石頭要賣多少錢啊?」

小和尚沒出聲,伸出一個指頭,那個人說:
「1000元?1000元就1000元吧,剛好我要用它雕刻一尊神像。」

小和尚聽到這裡,倒退了一步,嚇得說不出話!
但小和尚依然遵照師父的囑託沒有賣,趕緊抱回山上,去見師父,見到師父說:
「師父,今天有人要出1000元買我這塊石頭,這回您總要告訴我,我人生最大的價值是什麼了吧?」

老和尚哈哈大笑說:
「你明天再把這塊石頭拿到古董店門口去賣,但仍然不要賣掉它。你就把它抱回來。這一次,師傅一定告訴你,你人生最大的價值是什麼。」

小和尚聽後徹夜難眠,只恨天亮的太慢,好不容易到了天亮,他急忙捧著石頭跑到古董店門口,突然出現一名的拍賣師告訴他這是千年不遇的寶石,問他要賣多少錢,小和尚沒出聲,伸出一個指頭,拍賣師說:
「10000元?」

小和尚搖了搖頭,拍賣師出價說:
「100000元就100000元吧,我要好好珍藏它!」

小和尚聽了幾乎當場暈倒,趕緊抱回山上,去見師父,見到師父說:
「師父,今天有人要出100000元買我這塊石頭,這回你總要告訴我,我人生最大的價值是什麼了吧?」

老和尚指著石頭打斷他說:
「其實,我們並不打算賣它,不過現在你應該明白,為什麼石頭的形狀和外表都沒有變,而你的想法和做法卻再三變化呢,我之所以讓你這樣做,主要是想培養和鍛煉你充分認識自我價值的能力,和對事物的理解能力。

如果你是生活在菜市場,那麼你只有那個市場的理解力,你就永遠不會認識更高的價值。

不管你在什麼地方,同樣的你,有人將你抬得很高,有人把你貶得很低,有價值的東西,只有在懂價值的人面前,才有價值。不要管別人怎麼看,關鍵是自己怎麼看自己。

總而言之,你可以掌握自己的命運,決定自己的價值!」

2012年8月20日 星期一

2012 COSCUP

2012 COSCUP 我最喜歡的三個題目
(1)PQEMU: A Parallel System Emulator Based on QEMU 和 ARMvisor:ARM架構上系統虛擬機的實作

由清大的丁俊宏及Peter Chang介紹, 最令人興奮的是, 會open source code還會有文件呢!
https://github.com/podinx/PQEMU
http://www.cs.nthu.edu.tw/~ychung/conference/ICPADS2011.pdf


(2)How to write a SNES emulator in Javascript

Experimental Javascript Super Nitendo Emulators
http://weijr.b81.org/xnes/ 

由東華大學的助理教授:魏澤人,介紹一個他自己有興趣的題目.
主要功能是,將超級任天堂的模擬器移稙到Web based on Javascript
老師花了六天的時間將開源的SNEM經由LLVM轉成Javascript的程式. (超強啊)

感覺上似乎由此處進入LLVM的領域似乎也不錯呢!
或者是喜歡超任又想學寫Code的人, 玩玩這個應該也不錯吧!
改天等有空我也要來玩看看, 因為我想知道老師是怎麼處理Graphics/Audio的.

SNEM: http://www.tommowalker.co.uk/snem.html

(3)Jserv的第一次自幹作業系統核心就上手
在Jserv大大的1x分鐘的驚人寫code速度後, 回家後才想到, 不知到那時才能等到J大大的code, open出來耶XD
話說我居然完全忘了有OSDC了, 東翻西翻才看到原來Jserv大大今年也有講過
Embedded Virtualization in Daily Life (0xlab) OSDC.TW 2012


另外有兩個題目沒聽到, 要等影片檔了XD
(a)結合 Jenkins + Testopia 讓你的自動化測試和報告更Easy
(b)JavaScript 全面逆襲!使用 Node.js 打造桌面環境!


參考資料:
Testopia 中文用户手册.pdf
Embedded Virtualization in Daily Life (0xlab) OSDC.TW 2012

一個小故事讓我們明白資金流通的意義

“又是炎熱小鎮慵懶的一天。太陽高掛,街道無人,每個人都債台高築,靠信用度日。這時,從外地來了一位有錢的旅客,他進了一家旅館,拿出一張1000 元鈔票放在櫃檯,說想先看看房間,挑一間合適的過夜,就在此人上樓的時候---- 店主抓了這張1000 元鈔,跑到隔壁屠戶那裡支付了他欠的肉錢...