對我來說,在圖學領域探索的魅力在於,跟著開發者的思路讓不可見的狀態變得可見,並在腦海裡逐漸浮現背後的發展脈絡。
一直以來,我就對圖像的東西很感興趣,尤其是透過計算機畫出圖案來表達自己腦海中的想像。這類領域通常被稱為電腦圖學,對我來說,這是一個又一個的兔子洞。當看到某個新奇的圖像,或新的表達方式時,我就會充滿好奇。這些是怎麼一步步被實作出來的?用了什麼樣的渲染手法?該從哪個切入點開始了解?這些就像一個又一個的黑盒子,等待我去解密。
為什麼會說是黑盒子呢?以程式來說,我想換個角度形容,覺得圖像的東西有個特別的點是,撰寫時通常會在腦中有個圖像,但這些圖像演變的過程往往很難被記錄下來。好比說,某段過程用到了光線追蹤法,那撰寫的當下腦海中就會有個光線打到物體的想像,並根據這樣的想像把程式撰寫出來。然而,這樣一系列的想像和圖型生成的脈絡,往往很難在原始碼裡呈現出來。這些在渲染過程的中間狀態,就像謎團般的被層層封存,消失在作者過去的開發歷史裡,也催生了我的好奇心,期待一個個的發掘出來。
其中一個例子是 Inigo Quilez,如果你對圖學領域熟悉,你可能會聽過這個人,他對圖像渲染和數學之間的理解非常的熟稔。之前看到他的作品 Selfie Girl,就讓我很想了解這些東西是怎麼被一步步畫出來的,接著就是長達一個多禮拜的逆向工程,我儘可能的拆解了內部的所有程式碼,並讓中間的所有狀態變得可見,直到圖像能在我腦海中一步步的浮現出來。有種以另一種角度,也就是以 Inigo 本人的思考脈絡來看這個作品的感覺。
另一個我想提到的是 Bruno Simon,他開了一門叫 Three.js 的課程。讓我印象深刻的是,他特別擅長把程式的中間步驟一個個呈現出來。好比說,如果要展示像銀河系這樣的粒子系統,他會先隨機生成一千顆白點在正方體內,再逐步增加一些參數,像是粒子數目、半徑、分佈,再來是呈現出銀河系的骨幹,並讓骨幹有螺旋感,最後是加入隨機參數讓整體有星系的感覺。他盡可能的讓過程中的每一步能被直觀的理解,這對初學者在圖像的理解上幫助很大,也對整個過程有更深的認識。
然而,其實圖學領域對我來說還是有非常多黑盒子,許多細節或空間成形的過程往往只存留在開發者的腦海裡,這促使我想去拆解並重新建構他們的程式碼,並嘗試將這些發展過程的圖像一一拼回到我的腦海裡。聽起來可能有點抽象,所以我想用一個具體例子來說明這個過程。故事背景是這樣的,因為我最近在參加 Vesuvius Challenge,而這個時間點的所面臨技術挑戰是,要怎麼處理龐大幾何形狀的局部渲染,以及要怎麼快速計算之間的距離。這讓我很直觀的想到之前在 NASA JPL 待過的 Garrett Johnson,他有個專案叫 three-mesh-bvh,裡面的底層邏輯好像能解決我的問題。而這個專案的內部對當時的我來說就像個黑盒子,裡面充滿了未知的寶藏等待我去挖掘。儘管我第一時間能看懂這個專案大概在做什麼,但仍然有太多中間細節缺乏了具體圖像,好比說光線怎麼經過這些結構,BVH 的具體建構等等。唯有充分理解每步細節背後的圖像,才有可能運用在我所面臨的問題上。
於是我開始嘗試解析這個黑盒子,我覺得第一步是最有挑戰也最花時間的,那就是要找到一個切入點,將程式碼砍到自己能理解的最簡形式。以這個專案來說,我對樹的建構、光線追蹤、樹的視覺化、距離計算都不是很理解,但這些東西是有先後順序的,所有邏輯應該都會從樹的建構開始,於是我便試著把現有可執行的程式碼進行大量刪減,有時會報錯,有時會成功,總之我會盡可能把樹的建構以外的程式碼都刪除掉,並讓程式碼處於一個仍能執行的狀態。到了這步,可能還是會對整個程式沒有很理解,於是我會開始思考有沒有更簡單的圖像,好比說這個範例的樹狀結構還是太複雜了,我先改成只有兩個三角形好了,又或是曲面太難預測了,我先改成平面好了,就這樣一路繼續刪減下去。到了某個點會覺得現有的程式碼已經非常簡單,你對它已經有高度的掌握,這就是我所指的最簡形式,也就是程式碼的切入點。這步是最困難的,但通常找到了這個切入點,問題就進入了可解的範圍,也差不多處理掉一半了。
第二步剛好反過來,就是從切入點出發,依照先前的刪減經驗,一步步把整個脈絡搭配圖像給重新建構回來。這步的關鍵在於,思考怎麼從現有刪減後的程式加入一些新的程式碼,推進一點。這個推進需要有個看得到的圖像,而且不要跨太大步,盡可能用圖像來理解自己加入的片段。好比說,我發現這個專案會為樹建構 bounding box,所以我至少要先把 box 畫出來的函式還原回來,並暫時輸入一些假的資料點,確定看得到預期的結果。這步會排在前面是因為,如果沒辦法先將 bounding box 視覺化,獲得一個圖像,那我對後面樹的狀態演進將會像盲人摸象般的失去掌握。還有一點是,我會想辦法讓一些難以呈現的參數變得可見,先對這些參數的行為做一些想像並嘗試呈現出來。好比說,我對樹建構的過程中幾何點的重新排序有了大概的想像,於是我把這些想像透過一些方法視覺化出來,以便驗證這樣的想像,又或是我對光線行進的方式有些想像,於是改變了資料的形式來驗證自己預期的結果是正確的。整個過程其實有點像在做物理實驗,透過一步步的假設和實驗堆疊來推進自己對系統的認識。
通常這樣推進下去到某個階段,我會對整個專案的底層有十足的了解,也知道中間狀態是怎麼演進的。這個時候我並不一定會強迫自己要讀完它,而是思考現有的知識要怎麼運用到自己感興趣的問題上。好比說研究了一個禮拜後,我便開始寫一個 Python 版本的 BVH,專門用在處理 Vesuvius Challenge 的問題上。我覺得特別的是,如果這樣逐步建構的過程有被紀錄下來,那其實會是個很好的教學,因為每個跨步都是小且可見的,也紀錄了自己當時的思考脈絡,就像前面提到 Bruno Simon 在做的事那樣。
另外,想花點篇幅提一下這樣探索方式可能遇到的瓶頸,首先是最簡形式並不是在每個專案都能被找到,有些是受限於我理解的不足,有些則是尋找切入點或刪減上相對困難。再來是有時候許多參數或方法是有相依性的,這會讓我必須把它們都一起加進來才有辦法出現下個可見的結果,但這往往會飛躍太大步,導致那塊成為了只能用想像而無法視覺化的黑盒子。不過我還是會盡可能停下來思考,能不能拆解成更小的步驟並加以呈現,我的經驗是,大多時候都能做到這件事。
最後,隨著計算機能畫出來的圖像越來越真實,我更感興趣的反而是這些圖像作為想法傳遞的潛力,因為這些一個又一個的專案或渲染方式,其實背後都有許多開發者的思考脈絡,儘管是同樣且視覺上難以分辨的兩個場景,背後的渲染方式也可以全然不同。如果這些場景能進一步被拆解、探索、理解,那將會變得十分有趣不是嗎!