Re: [閒聊] 老遊戲的變態程式碼
※ 引述 《Senkanseiki》 之銘言:
: 標題:[閒聊] 老遊戲的變態程式碼
: 時間: Tue Jul 22 16:45:40 2025
:
: https://www.youtube.com/watch?v=n2Q1Sp7iew4
: https://en.wikipedia.org/wiki/Fast_inverse_square_root
:
: 1999年製作的一款遊戲:Quake III Arena
: 在遊戲開發者之間,這款遊戲的程式碼成為了熱門話題
: 因為下面這個求1/√x的程式碼實在太變態了而讓大家頗為驚訝
:
: 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
:
: return y;
: }
這個東西很有名的,是雷神之鎚3的「反平方根快速演算法」
https://bit.ly/4f6pYx0
其實目的就是要計算1/ √x的數值
比方說,如果x=9,因為√9=3,1/√x就等於1/3,大約是0.3333…
所以9的反平方根就是0.3333…
看起來很簡單吧?
但反平方根這個東西,最大用途是計算遊戲內部的光影變化
——————
太複雜的內容就不說太細,簡單說一個概念
「光的漫射」
舉現實的例子來說,用手電筒照牆壁
>你光源直接照牆壁,會很亮
>稍微斜著照,牆就沒那麼亮
>照牆的背後,當然完全不會亮
https://i.imgur.com/8aMtyTK.jpeg

以前國中物理還記得的話,上面的虛線就是光的法線
實際物理計算上,需要知道入射光的方向角度和法線夾角、才能知道反射光的方向,以及整
體漫射後光影強度
那怎麼用數學計算呢?
就是高中數學的「向量」還有「內積」
忘記的可以去翻翻以前的課本或教科書w
總之,計算漫射光強度公式大概這樣
https://i.imgur.com/siNXtY8.jpeg

可以把公式看成是遊戲內的「亮度計」
為了讓計算準確,牆的朝向和光線方向都需要要「標準化」
換言之,需要計算單位向量(向量座標除於向量本身的長度)
https://i.imgur.com/uh46f3v.jpeg

然後很自然的,就需要用到平方根的值
https://i.imgur.com/cBozOny.jpeg

這就是反平方根的角色——幫忙快速把向量縮到標準長度
而且這樣計算可以直接算出光線與牆的「對齊程度」,不用真的去量角度,或是更複雜的三
角函數計算
省去了計算的時間
——————
不過以上說的是物理和數學概念
這個程式碼厲害的地方是,在當時那個年代之中,用最少的計算成本來算出需要的平方根
這部分我就不太清楚,只簡單說一下
當x的值輸入後,程式碼不是直接帶入數字,而是「駭入」到位元層級
: i = * ( long * ) &y; // evil floating point bit
: level hacking
然後以魔術數字「0x5f3759df」為起點
這是16進位的數字,對應十進制的1597463007
套用公式直接找出平方根的初始值
: i = 0x5f3759df - ( i >> 1 ); // what the fuck?
: y = * ( float * ) &i;
當然,這樣可能還有誤差,於是還有兩次校正,用到的就是牛頓法
提高y的精準值,提升平方根的準確度
: y = * ( float * ) &i;
: y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
: // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can
: be removed
整個計算法神秘的是,當初是怎麼找到
魔術數字「0x5f3759df」的?
雖然有人說是作者卡馬克寫的,但實際情況是…
約翰.卡馬克:我他媽的怎麼知道!
對,沒有人知道是哪個天才寫的程式嗎
但因為很好用所以就留著了,只有後來工程師看到內容後,留下很有名的註解
//what the fuck ?
https://i.imgur.com/U8vUDEP.jpeg

——————
有錯誤的就麻煩指正一下w
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.219.68.127 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/C_Chat/M.1753179889.A.236.html
推
07/22 18:28,
5小時前
, 1F
07/22 18:28, 1F
推
07/22 18:32,
5小時前
, 2F
07/22 18:32, 2F
推
07/22 18:35,
5小時前
, 3F
07/22 18:35, 3F
推
07/22 18:37,
5小時前
, 4F
07/22 18:37, 4F
推
07/22 18:38,
5小時前
, 5F
07/22 18:38, 5F
→
07/22 18:42,
5小時前
, 6F
07/22 18:42, 6F
推
07/22 18:42,
5小時前
, 7F
07/22 18:42, 7F
推
07/22 18:43,
5小時前
, 8F
07/22 18:43, 8F
推
07/22 18:49,
5小時前
, 9F
07/22 18:49, 9F
推
07/22 18:57,
5小時前
, 10F
07/22 18:57, 10F
→
07/22 18:57,
5小時前
, 11F
07/22 18:57, 11F
推
07/22 18:58,
5小時前
, 12F
07/22 18:58, 12F
推
07/22 19:00,
5小時前
, 13F
07/22 19:00, 13F
推
07/22 19:16,
5小時前
, 14F
07/22 19:16, 14F
→
07/22 19:24,
4小時前
, 15F
07/22 19:24, 15F
推
07/22 19:46,
4小時前
, 16F
07/22 19:46, 16F
→
07/22 19:46,
4小時前
, 17F
07/22 19:46, 17F
→
07/22 19:46,
4小時前
, 18F
07/22 19:46, 18F
→
07/22 19:46,
4小時前
, 19F
07/22 19:46, 19F
推
07/22 20:00,
4小時前
, 20F
07/22 20:00, 20F
推
07/22 20:17,
4小時前
, 21F
07/22 20:17, 21F
推
07/22 21:21,
2小時前
, 22F
07/22 21:21, 22F
推
07/22 23:09,
1小時前
, 23F
07/22 23:09, 23F
討論串 (同標題文章)
C_Chat 近期熱門文章
PTT動漫區 即時熱門文章
9
39