一、前言
記得很久很久以前,在ShaderToy上看過一個黑洞的效果,當時感覺太*8帥了,于是這幾天就嘗試自己弄了一個。

?
下面是我自己實現的黑洞
可以看到還是略遜一籌(感覺略遜百籌)。主要是吸積盤的紋理細節不夠豐富,以及Bloom的調整。
本文著重介紹原理,工程實現等有空再寫一篇文章。
二、引力透鏡效應?
引力透鏡效應,簡單的說就是因為黑洞的質量太大,導致光線彎曲,以至于我們能看見黑洞后面的東西。如上圖所示,如果綠色的球是某種發光物體,紅色是光線原本應該發出去之后的方向,但因為黑洞的引力太大導致光線發生了彎曲,進入了人的眼睛,于是我們便看到了該物體(在眼睛的第一視角,這個綠色的球應該是一個綠色的環圍著黑洞)。?、
而另一些光線就沒那么幸運了,比如方向朝向黑洞中心的光線,它們收到的引力更大,無法逃逸,所以就不會被我們看見了。
傳統的渲染都是默認我們的光線沿直線傳播,但這里不同,光不再沿直線傳播了。于是想要更精確的模擬光線的彎曲就只能使用RayMarching了,也就是光線步進。
那么光線如何彎曲呢?
很簡單,我們并不需要精確模擬,所以也不需要太復雜的公式,只需要簡單的高中物理知識就能模擬一個大概的樣子。簡單地說光線原本沿直線傳播,但因為黑洞的存在,我們需要在光線步進的途中時刻改變它的方向,用什么改變呢,當然是加速度了。記得嗎?加速度也是矢量。
在光線步進的途中,根據萬有引力定律求出當前點所受的引力就可以求出當前點的加速度大小和加速度方向,根據加速度改變下一次步進的方向和距離,最后采樣就可以了。
三、SDF體渲染
黑洞中心的事件視界黑球,我們采用了SDF體渲染的方法,規定一個球心和一個半徑,接著使用球的SDF,如果光線進入到了這個范圍,直接返回黑色就好了。

吸積盤同樣用SDF體渲染的方法,規定一個半徑,然后高度隨半徑衰減就可以了。
最后如果之前光線步進到吸積盤上,就返回吸積盤的顏色就好了。
為吸積盤添加紋理,實現更多細節。當然也可以采用三維紋理。當然,你要先把紋理轉為極坐標,否則無法形成旋轉效果。
最后加上Bloom等后處理,一個黑洞就誕生了。
參考資料?
在Unity中渲染一個黑洞 - GuyaWeiren - 博客園 (cnblogs.com)
如何渲染一個黑洞(一) - 知乎 (zhihu.com)