2013年8月29日 星期四

Rendering 3D Anaglyph in OpenGL - 4

since: 2013/08/24
update: 2013/08/29

reference:
0. 原文: Rendering 3D Anaglyph in OpenGL
1. I touchs: Rendering 3D Anaglyph in OpenGL - 1
2. I touchs: Rendering 3D Anaglyph in OpenGL - 2
3. I touchs: Rendering 3D Anaglyph in OpenGL - 3

G.
立體視錐變量

      1. 到此為止, 我們已經有充分的認識, 可以計算立體視錐的變量, 以用在將來的
          OpenGL 程式中. 觀察以下的圖示:

                                                      圖九: 計算視錐變量

      2. 雖然上面這張圖看起來蠻可怕的, 但是實際上並沒有加入新的資料. 如果, 到
          目前為止你都瞭解所有討論的東西, 你將可以輕而易舉地從頭到尾聽懂這簡單
          的計算. 如之前所述, 二個攝影機位在 X 軸上的 L 點與 R 點. L與R這二點的間隔
          為 Deye, 並且它們的位移是對稱於原點的. 二台攝影機的方向是平行的, 都是
         朝著負 Z 軸方向. 視錐的近截距(near clipping distance)為 Dnear , 收斂距離為 C.
         從頂視圖來看, 虛擬螢幕的二個端點為 A 與 B. A 點為二個視錐的左邊會合之處,        
         而 B 點為二個視錐的右邊會合之處.

      3. 在 OpenGL 中, 建立非對稱視錐的唯一方式是經由 glFrustum(). 而 
           gluPerspective() 只能建立對稱的視錐, 因此在此例中不能使用.
           gluPerspective() 採用自然觀看的變量, 例如: 沿著 Y 方向的視野
           (field of view) θFOVY (見: 圖. 七(a)), 以及視錐的寬高比(aspect ratio),
           近截距和遠截距. 然而, 對於 glFrustum(), 你必須要提供近截面
           (near clipping plane)的上, 底, 左與右邊的座標, 而且還要有近截距和遠截距.
           我們將會從上方的二個視錐幾何中, 計算這些變量.

      4. 在圖中, 對應於虛擬螢幕的單一視錐等同於 AOB. 其沿著 Y 方向的視野為:
          θFOVY , 並且寬高比為 raspect (在 gluPerspective() 中也是如此).
         
      5. glFrustum() 函式:
          glFrustum( GLdouble leftX, GLdouble rightX,
                                GLdouble bottomY, GLdouble topY,
                                GLdouble nearZ, GLdouble farZ);


      6. 所以, glFrustum() 中的頂部和底部座標計算為: 

top=DneartanθFOVY2


bottom=top

          這些值, 同時適用於左邊和右邊的視錐.

          虛擬螢幕的一半寬度 a 為:

a=raspectCtanθFOVY2

         接著, 看看左邊的視錐 ALB. 近截面與 LL 左邊相交的距離為 dleft , 而與 LL
         右邊相交的距離為 dright. 在三角形 ΔALL 與三角形 ΔBLL中,

dleftb=drightc=DnearC
         而且, 我們也知道:
b=aDeye2

c=a+Deye2

         所以, 我們就能夠很快地計算出 dleftdright. 同樣地, 在右邊的視錐 ARB 中,
         藉由交換 b 與 c 的值, 就可以獲得 dleftdright 的值. 

Rendering 3D Anaglyph in OpenGL - 3

since: 2013/08/22
update: 2013/08/29

reference:
0. 原文: Rendering 3D Anaglyph in OpenGL
1. I touchs: Rendering 3D Anaglyph in OpenGL - 1
2. I touchs: Rendering 3D Anaglyph in OpenGL - 2

F.
OpenGL 攝影機:

     1. 剩下唯一要討論的任務是: 如何在 OpenGL 裡設置雙重的攝影機. 在非立體模式,
         你只需要一個攝影機, 其觀看的參數由 glFrustum()gluPerspective() 所定義.
         所得到的視錐(平截頭體 frustum)看起來如下所示:  

                                                      圖七(a): 單一視錐

                                                      圖七(b): 單一視錐(從上方垂直觀看)

     2. 然而, 繪製出立體感需要設置雙重的攝影機, 類似以下的狀況: 

                                                      圖八(a): 立體表現的雙攝影機系統

     3. 在這個結構當中, 我們有二個視錐: 一個來自 L 點(提供給左眼), 另一個來自R 點
         (
提供給右眼). 距離 LR 為兩眼間隔, 所以 L 點跟 R 點分別沿著 X 軸的原點位移
         了負 LR/2 與正
LR/2 的量. 觀察力敏銳的讀者, 可能已經注意到上圖的二個視錐,
        
與之前展示的
單一視錐是不同的, 我們並不是將單一視錐沿著 X 軸位移來得到雙
         攝影機系統的.
事實上, 上方顯示的這二個
視錐是非對稱的(asymmetric), 而單一
         視錐是
對稱的(symmetric)(p.s.幾何形狀, 請看下二張圖來更加瞭解).   
         如果這二個視錐是對稱的, 並且在之後作了橫向位移, 它們將不會收斂在一起. 
         非對稱才會致使這二個視錐在收斂距離處會合. 位在收斂距離上的洋紅色矩形
         代表
立體上的虛擬螢幕. 任何在虛擬螢幕上的頂點, 顯示上是零視差的. 而接近
         或遠離這個距離的頂點, 會產生適量的負或正視差.


     4.下面的圖, 顯示從頂部垂直觀看同一個的系統:

                                                      圖八(b): 立體視錐 (從頂部垂直觀看)

     5. 上方, 可以明顯地看出視錐的不對稱. 並且注意到, 每個視錐的觀看方向是相互
         平行的, 同時也與 Z 軸平行,
單一視錐也是一樣. 這是設置一對立體攝影機的正確
         方式. 還有另一種設置雙重攝影機的方式稱作: 內八字(toed-in)攝影機, 它採用
         對稱的視錐, 但是左右的觀看方向互為一個角度. 這足以說明, 內八字(toed-in)
         攝影機的設置是不正確的.  
 

     6. 還有另外一張沿著 Z 軸來顯示立體攝影機系統的圖: 

                                                      圖八(c): 立體視錐 (靠在椅背上垂直觀看)

Rendering 3D Anaglyph in OpenGL - 2

since: 2013/08/22
update: 2013/08/29

reference:
0. 原文: Rendering 3D Anaglyph in OpenGL
1. I touchs: Rendering 3D Anaglyph in OpenGL - 1

E. 視差方程式:
      1. 之前提到, 視差可在品質上度量到. 現在開始要在位於某個深度的頂點, 引進視差
          的觀念來獲得方程式. 要畫出立體浮雕, 所需設定的 OpenGL 並不是重要的關鍵,
          重要的是在你的互動應用中, 所繪製的場景全部範圍都要使用合適的視差. 考慮
         下面的圖解, 其中, 頂點 V 位在深度 w, 並且是在收斂距離 C 再往後的地方:
     
                                  圖四: 測量位在收斂距離 C 後方的頂點 V 之視差值

      2. 兩眼間隔為 D, 收斂距離為 C. 連結左邊攝影機 L 與頂點 V 的線, 在收斂平面上
          相交為 P. 同樣地, 連結右邊攝影機 L 與頂點 V 的線, 在收斂平面上相交為 Q.
          與頂點 V 相關聯的視差距離 PQ 定義為 p(小p). 現在, 考慮三角形 LVR,
          從截線定理(intercept theorem)可以得到:

PQLR=VQVR

          類似地, 在三角形 QVM 與 VRN 中, 我們可以得到:


VQVR=VMRN=wCw=1C/w

          因此, 

PQLR=pD=1C/w
          或
p=D(1C/w)

      3. 類似地, 下面的圖為比收斂距離更近的頂點: 

                                  圖五: 測量位在比收斂距離 C 更近的頂點 V 之視差值                                      

      4. 與頂點 V 相關聯的視差距離 PQ: p(小p), 可以再次套用截線定理獲得:

PQLR=QVVR=QVQRQV=QVQR1QVQR
           在三角形 QNR 中, 因為 VM 平行 RN, 因此:


QVQR=VMRN=CwC=1w/C
           因此,
PQLR=pD=1w/Cw/C=C/w1
           或,
p=D(1C/w)

      5. 這個方程式與位在收斂距離後方的頂點相同, 只差了一個負號. 負號意味著:
          收斂平面上的頂點投影, 相對於攝影機是在相反的一側. 如果忽視方程式中
          的正負符號, 負視差可以被理解成: 頂點開始移動得比收斂距離更近.
          p=D(1C/w)可繪製成以下的圖:
 
                                  圖六: 給定收斂距離與兩眼間隔, 頂點深度的視差變化量

      6. 圖中顯示, 當頂點移動越遠離場景, 所產生的視差越接近兩眼間隔 D.
          在收斂距離 C 的地方, 視差為零; 而所有深度大於收斂距離的頂點, 視差皆保持
          正值. 在場景中, 所有比收斂距離 C 更近的頂點, 視差為負值, 並且快速地接近
          無限大. 注意到, 當頂點的深度 w 等於 C/2 時, 所得到的視差值等同於兩眼間隔.
          過大的負視差, 會使觀察者的眼睛視線偏離, 而造成變形, 應該避免.
          根據攝影機的鏡頭與所要拍攝的效果(浮出螢幕或沈入螢幕)作為基準, 來選擇
          實用的收斂深度. 典型的兩眼間隔保持在收斂距離的 1/30, 並且在場景中,
          要避免讓物體近於收斂距離一半的位置上. (即: 深度不可小於 C/2 )
           

Rendering 3D Anaglyph in OpenGL - 1

since: 2013/08/13
update: 2013/08/29

reference:
0. 原文: Rendering 3D Anaglyph in OpenGL

A. 說明:
     本系列為翻譯文章, 以及在 Mac OS X 上的實作練習, 翻譯的內容可能有所誤差
     或尚未能完整表達原作著的意思, 並添加了部分個人的註解說明.

---------------------------------------------------------------------------------

B. 概要:

     1. 使用 OpenGL 來畫出 3D 立體圖片(anaglyphs) 是一件相當容易(且有趣)的事.
         希望你知道什麼是立體圖片(anaglyphs), 並且懂得如何去觀看它們. 如果不清楚
         的話, 請閱讀之前的這篇文章. 這篇教學文章的焦點是要提供你足夠的背景知識,
         與片段的程式碼來完成之後的工作. 之後, 你就可以在自己的程式中, 畫出有趣
         的立體圖片.

     2. 我們的焦點會放在: 從一個給定的 3D 場景, 來產生紅藍立體圖片
         (red-cyan anaglyph). 這個場景將會被繪製二次: 一次是給左眼觀看的攝影機,
         僅允許讓紅色光線通過; 另一次是給右眼觀看的攝影機, 僅允許讓青綠色(綠+藍)
         光線通過. 要實作這個想法, 你需要了解在立體視覺(stereoscopic vision)當中,
         視差(parallax)所扮演的角色, 以及應用在 OpenGL 上的投影(projection)與
         視野(viewing)之概念. 這篇教學文章假定你熟悉 OpenGL 投影(projection)與
         模型視野(modelview)的轉換( transforms), 如果你了解那些內容就繼續閱讀;
         不然的話, 請閱讀 紅皮書 中的這個章節, 以作好準備. 

---------------------------------------------------------------------------------

C. 視差觀念:

    1. 什麼是視差(parallax)? 當你未使用紅藍立體眼鏡來觀看 3D 立體圖片時, 會發現
        圖片中物體的邊緣有紅色與青綠色的成份. 請觀察底下的圓柱體(cylinder):

                                                      圖一: 浮雕例子 - 圓柱體
    2. 在現實裡, 我們眼中的物體藉由在左眼與右眼間橫向位移的量產生了立體感,
        因此, 在平面的影像上(照片或顯示螢幕), 人類的視覺系統需要深度(depth)的
        訊息, 才能產生立體的視覺效果. 當我們談到視差, 就是意指影像中的這種確切
        的位移. 要在上方的圖片中看到視差的效果, 使用紅藍(red/cyan)立體眼鏡
        (紅色在左眼), 並試著將滑鼠指標停留在稍微超出圓柱體左邊的末端. 這樣
        看起來: 圓柱體左邊的末端是沈入螢幕內; 相反的, 圓柱體的前端(右邊)似乎
        或多或少以相同的深度浮出螢幕. 所以, 要畫出浮雕(anaglyph)的效果, 我們
        要試著去完成的是: 在場景中(scene)為物體取得正確種類的視差, 其餘的部分,
        人類的大腦會免費自動地完成!   

---------------------------------------------------------------------------------

D. 視差基礎:
      1. 視差不僅是一種性質上的呈現, 它有數值, 並且可以是正值, 負值或零.  
          在應用中, 視差的建立基於以下: 定義二個對應於分隔一段距離的左右眼
          (稱為: 二眼之間的距離或簡稱: 兩眼間隔)之攝影機, 並且沿著視線方向在
          某個深度會有一個平面(稱為: 收斂距離 convergence distance), 在那裡,
          視差為零. 位在收斂深度上的物體, 看起來與螢幕是在相同的深度. 物體位在
          比收斂距離更接近攝影機的地方, 看起來似乎是從螢幕走出來; 而物體位在
          比收斂距離更深遠的地方, 看起來似乎是在螢幕內部. 下面的圖例說明了
          這些狀況:      

                                                      圖二: 位在不同深度的頂點視差

      2. 在這張圖片中, 有二個虛擬的攝影機, 一個是模擬左眼的位置(沿著 X 軸方向,
          對原點上作少量的負位移), 另一個是模擬右眼的位置(沿著 X 軸方向, 對原點
         上作少量的正位移). 這二個攝影機被分開的距離, 等同人類左右眼之間的位移量,
         其值平均大約是65公釐(6.5公分). 於是, 會有一個零視差的深度稱為收斂深度.
         你可以把它想像成是沿著負 Z 軸方向, 位在收斂深度的地方, 有一個順著 x-y 軸
         的平面. 圖中顯示的三個頂點: v1, v2 和 v3, 將用來說明不同種類的視差.

      3. 對每頂點(v1, v2 和 v3), 想像有條線分別從頂點連到每個攝影機, 並觀察與收斂
          平面相交在何處. 左右眼攝影機在收斂平面上交會的二點之間隔, 就是該頂點所
          產生視差的判斷基準: 
 
          a. 頂點 v1:
              相對於收斂處, 位於更大的深度而產生了視差. 可以觀察到在收斂平面上的紅點
              與青綠(cyan)點, 與二個攝影機是同向性的: 紅點是朝著左邊的攝影機方向, 青綠
              (cyan)點是朝著右邊的攝影機方向. 這樣子稱為正視差, 而且當影像繪出時, 頂點
              v1 會顯示在螢幕內部(沈入).       

          b. 頂點 v2:
              位於與收斂平面相同深度的地方產生零視差. 正如之前的例子, 在此, 收斂平面
              處沒有被分隔的紅點與青綠(cyan)點. 當影像繪出時, 頂點 v2 會顯示在與螢幕
              相同深度的地方.  

          c. 頂點 v3:
              位在比收斂距離小的地方, 也產生了視差. 但是投射在收斂平面上的紅點與青綠
              (cyan)點, 與攝影機的位置是反向的. 對應到左邊攝影機的點在收斂平面上是偏往
              右邊, 而對應到右邊攝影機的點在收斂平面上是偏往左邊. 這樣子稱為負視差,
              而且當影像繪出時, 頂點 v3 似乎顯示在螢幕外部(浮出).

      4. 再看看另一個浮雕, 說明了頂點在不同的深度所產生的典型視差: 

                               圖三: 二十面體所顯示的負, 零與正視差(比原圖失真許多)

      5. 在圖中, 有三個二十面體. 在底部的那一個, 是場景中最遠的; 在頂部的那一個,
          是離攝影機最近的. 位在中間的二十面體, 是幾乎與螢幕位在相同的深度. 注意到
          產生最近和最遠二十面體的視差方式, 是有著相反的組合.(以下解釋) 最近的二十
          面體, 右邊有紅色的邊緣, 左邊有青綠色的邊緣. 當用3D紅藍眼鏡觀看, 這表示
          負視差(紅色濾鏡在左眼), 二十面體稍微地顯示在螢幕外部(浮出). 然而, 圖片中
          底部最小的二十面體, 左邊有紅色的邊緣, 右邊有青綠色的邊緣. 這種組合與用來
          觀看的有色眼鏡是相同的. 所產生的是正視差, 二十面體顯示在螢幕內部(沈入),
          在位於中央二十面體的後面. 而位在中央的二十面體, 是與螢幕有著相同的深度,
          畫出來幾乎沒有視差(零視差).