魚眼投影方式(Fisheye projection)的軟件實現


簡單實現

魚眼模式(Fisheye)和普通的透視投影(Perspective projection),一個很大的區別就是魚眼的投影算法是非線性的(non-linear),實際照相機的情況是在鏡頭外面包圍一個半球體,將場景通過半球體投影到畫布上。大致如下:

               M
                 x                 
                  \                
                   \  ______       
                 M'_x'      `-.
                 ,' |\         `.
                /   | \          \
               /    |  \          \
              |     |   \          |
    __________|_____|____\_________|_________
                    M"    O        1
                    
M: world position
M': projection of M on the unit hemisphere
M": projection of M' on the unit disc (= the screen)

上面這個示意圖來自stack exchange 的回答,是Sam Hocever畫的

vertex shader 繪制一個長寬均為1的正方形,作為遠處的物體,紋理實際貼在這個正方形上面。

在 fragement shader 內將上面的這個算法實現即可。

設我們在屏幕上的點為(x0, y0) 直接得到外面球面上的點是
(x0, y0, z0) and z0 = sqrt(1 - x0^2 - y0^2)
遠處平面上的點和球面上的點共線所以坐標成比例關系,直接設x1 = a * x0然后假設我們的遠處的物體就是一個平面,處於 z1 = -1 的位置,直接得到:

因為: 
abs(z1) = 1 = z0 * a
z0 = sqrt(1 - x0^2 - y0^2)
所以:
a = 1.0 / z0 = 1.0 / (sqrt(1 - x0^2 - y0^2))

當然遠處平面的位置可以調整,離的近就大,離的遠就小,但是大小是不變的,仍然是一個邊長為 1 的正方形。所以可以調整的就是這個距離,也是 z1 的值。Sam Hocever 提供的思路是改變這個投影的 fov 的值。當 fov = PI / 2 時,和我剛剛設定的值一樣,z1 = -1。兩者關系為
z1 = 0.5 / tan(theta / 2)

總結:a = z1 / z0 = 0.5 / ((sqrt(1 - x0^2 - y0^2)) * tan(theta / 2))

其他實現方式

主要參考 Computer Generated Angular Fisheye Projections
上文介紹了兩種投影的方式,第一種前文已經解釋,后一種方式我正在學習中。

另外還有一個經典的項目,blinky
提供另外一種解決的辦法,先弄出一個包圍盒,紋理貼在包圍盒上,然后在轉換成魚眼效果。
具體的實現看源碼。

本文的主要參考鏈接

[How do I create a wide-angle / fisheye lens with HLSL?](http://
gamedev.stackexchange.com/questions/20626/how-do-i-create-a-wide-angle-fisheye-lens-with-hlsl)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM