光線追蹤器在實現光線折射時,玻璃球出現奇怪的黑圈?
在寫光線追蹤器,紋理,反射,陰影什麼都寫的很順利,但是最後一個折射功能卡住我兩天了T_T。不明原因,玻璃球在折射的時候,最外圍出現了一個黑圈。
如果我把材料折射率調大,黑圈變粗,調小直到1,黑圈消失,完全透明。我發現玻璃球確實在折射,因為玻璃球實現了類似凸透鏡的效果。但是這個黑圈想不通是哪裡來的。下一步debug該從哪下手呢,我重新寫了遍代碼還是沒什麼想法,其他措施如檢查了critical angle也沒效果,求大家給點思路。謝謝。
我的圖片因為格式問題無法上傳到知乎,用的是其他人類似的圖片。PS:同性交友網站上有類似問題及答案,但是答案對我的問題不起作用。
謝邀。。我試了下把你的bug reproduce出來了。。也是醉了- - 請叫我紅領巾。。
主要由兩個bug造成。
1. 你那個Sphere的法線反了。你所有法線都是指向球心的。所以球心部分的折射沒有被影響的比較少,而球的外圍則變成了出從法線的反方向射入,也就是出射的情況,然後你的折射率又大於1.0,所以就黑了。。你圖片裡面那個凸透鏡的效果沒有上下左右顛倒也說明法線反了。。
2. 你只計算了折射沒計算反射。。光線打到這種Dielectric材質都是即會反射也會折射的,然後用fresnel去算折射和反射的權重係數,包括在球的內部,也會反射來反射去。。
剛才實現了你這兩個bug,就出了下面的效果圖。。
反射率為1.14和1.75的情況。。


沒有bug應該是這樣。。

寫這種程序的確建議弄一個輪子哥說的那種可以隨時debug某個像素的機制。最簡單的你就看看那個像素出了問題,然後專門生成那個像素的光線一步一步跟進去看最後為什麼會是黑色的。。而且debug的時候你可以先disable反射的光線,只看折射的。不然光線還在球內部反射來反射去的很乾擾你。。
全反射了?
你可以試試看弄成單面的折射,並且把折射後的射線方向作為顏色畫出來。如果不是bug的話,應該是連續的。通常實現renderer的時候,折射都有上限,估計到達了上限你也沒有處理直接返回黑,結果就全黑了。你可以學 @Yong He ,滑鼠點在一個像素上面的時候,給出這次ray tracing的幾條光線的參數並畫出來,然後就什麼都明白了。
補充一下文刀秋二的回答。
今天偶然發現另一個可能導致黑圈的原因……
首先出現黑圈肯定是因為光線在錯誤的地方發生全反射。出現這個bug,除了法線方向錯誤以外,還有可能是因為在計算折射時入射光向量或者法向量沒有化為單位向量。這個問題不僅會導致在計算折射時渲染出黑圈,而且渲染得到的黑圈厚度也會隨折射率大小變化,黑圈內部的像在較高折射率下也是倒過來的。
這個bug比法線方向錯誤還要隱蔽。也許題主不是因為這個問題出錯的,但我覺得也有必要提一下……我以前也遇到過類似的情況,不過我的是規則球體正常,而扁橢球體的會出現很寬的黑邊。初看上去像全反射,但是全反射不可能有那麼大的黑邊。後面把調試數據導入到Mathematica分析了很久才發現原來是法線進行transform的時候出錯了。我當時是把法線當成點直接進行transform的,實際上法線不能直接左乘變換矩陣進行變換,正確的方法可以參考這個OpenGL Normal Vector Transformation。
推薦閱讀:
※OpenGL shader如何調試?
※path tracing 渲染bunny glass材質,為什麼會有奇怪的黑色?
※像玻璃球這種透明且帶有折射現象的物體如何進行實時渲染?
※學計算機圖學時,自己寫的軟渲染器代碼結構是否應模仿OpenGL的狀態機模式?
※為什麼CryENGINE3引擎號稱最強大、最真實的引擎,但在孤島危機2/3當中的畫面仍然有一種光澤度過強的塑料質感?

