我們用 81x40 個 ASCII 字元,向 -Z 軸方向渲染一個單位球 :
編譯執行結果:
解釋一下,這個單位球是投影在 平面上,所以 y 從上至下、x 從左至右迭代;而一般半形文字的顯示長寬比是 2:1, y 軸用 1 / 20 = 0.05 增量,x 軸用 1 / 40 = 0.025。
我們知道單位球投影在 平面後,會在單位圓的範圍,即 ,在這範圍內渲染單位球的表面,範圍以外填上背景("M" 字元)。
為了表示立體感,需要按球體表面的法線著色。單位球的表面法線等同於表面位置,表面位置/法線可以從單位球的方程解出:
因為面向我們的一面球面是向 +z 方向的,z 值取正號便可。
然後,通常著色的 Lambert 項是:
當中 為光源方向, 為法線。需要 max 是因為兩者夾角超過 90 度是不會獲得光照。但這裡採用了一個名為 Half Lambert 的方案(最先用於《Half Life》遊戲),把著色的過渡從 0 至 90 度,擴充套件至 0 至 180 度,使整個球體表面都有過渡著色(這種非物理正確的方法可用於模擬 SSS 或卡通化的效果):
(左為 Lambert 項,右為 Half Lambert 項)
為簡單起見,我們採用 作為光源方向,那麼著色就變成:
最後,我們把亮度結果對映至 10 個字元。
相關答案和文章
我們用 81x40 個 ASCII 字元,向 -Z 軸方向渲染一個單位球 :
編譯執行結果:
解釋一下,這個單位球是投影在 平面上,所以 y 從上至下、x 從左至右迭代;而一般半形文字的顯示長寬比是 2:1, y 軸用 1 / 20 = 0.05 增量,x 軸用 1 / 40 = 0.025。
我們知道單位球投影在 平面後,會在單位圓的範圍,即 ,在這範圍內渲染單位球的表面,範圍以外填上背景("M" 字元)。
為了表示立體感,需要按球體表面的法線著色。單位球的表面法線等同於表面位置,表面位置/法線可以從單位球的方程解出:
因為面向我們的一面球面是向 +z 方向的,z 值取正號便可。
然後,通常著色的 Lambert 項是:
當中 為光源方向, 為法線。需要 max 是因為兩者夾角超過 90 度是不會獲得光照。但這裡採用了一個名為 Half Lambert 的方案(最先用於《Half Life》遊戲),把著色的過渡從 0 至 90 度,擴充套件至 0 至 180 度,使整個球體表面都有過渡著色(這種非物理正確的方法可用於模擬 SSS 或卡通化的效果):
(左為 Lambert 項,右為 Half Lambert 項)
為簡單起見,我們採用 作為光源方向,那麼著色就變成:
最後,我們把亮度結果對映至 10 個字元。
相關答案和文章
如何用 C 語言畫「心形」? - 知乎如何用 C 語言畫一個“聖誕樹”?馬賽克球體如何用AI或者PS做出來? - 知乎如何用 C 語言畫這個圖 - 知乎專欄用 C 語言畫科赫雪花 - 知乎專欄