1. 程式人生 > >計算機圖形學——光線追蹤(RayTracing)演算法

計算機圖形學——光線追蹤(RayTracing)演算法

前言

最近處於畢設答辯前的空檔期,沒什麼要緊的事情要做,於是空閒之餘隨意看了下點計算機圖形學,學習了一個畫3D圖形的光線追蹤演算法,在此簡單地分享一下~

一、理論基礎

1、三維場景中建立影象
  • 第一步:透視投影。這是一個將三維物體的形狀投影到影象表面上的幾何過程,這一步只需要連線從物件特徵到眼睛之間的線,然後在畫布上繪製這些投影線與影象平面相交的輪廓。
  • 第二步:新增顏色。影象輪廓繪製好之後,給它的骨架新增顏色,這樣就完成了三維場景中的影象建立過程。



2、物體的顏色和亮度
  • 主要是光線與物體材質相互作用的結果。
  • 光由光子(電磁粒子)組成,光子由各種光源發射。當一組光子撞擊一個物體時,可能發生三種情況:被吸收,反射或透射。發生這三種情況的光子百分比因材料而異,通常決定了物體在場景中的顯現方式。然而,所有材料都有一個共性:入射光子總數總是與反射光子、吸收光子、透射光子的總和相同。
  • 白光由“紅”、“藍”、“綠”三種顏色光子組成。當白光照亮紅色物體時,光子吸收過程會過濾掉“綠色”和“藍色”光子。因為物體不吸收“紅色”光子,所以它們將被反射,這就是物體呈現紅色的原因。
  • 我們之所以能夠看到物體,是因為物體反射的一些光子向我們傳播並擊中了我們的眼睛。我們的眼睛由光感受器組成,可以將光訊號轉換為神經訊號,然後我們的大腦能夠使用這些訊號來辨別不同的陰影和色調。
3、光與物體的關係
  • 沒有光線,我們都看不到周圍的物體。
  • 周圍環境中沒有物體,我們看不到光。

二、光線追蹤(RayTracing)演算法描述

1、Forward Tracing

在用計算機生成的影象中模擬光與物體相互作用過程之前,我們需要了解一個物理現象。一束光線照射在物體上時,反射的光子中只有少數會到達我們眼睛的表面。想象一下,假設有一個每次只發射一個光子的光源,光子從光源發出並沿著直線路徑行進,直至撞擊到物體表面,忽略光子的吸收,該光子會以隨機的方向反射。如果光子撞擊到我們的眼睛表面,則我們會看到光子被反射的點。具體過程如下圖所示。


現在從計算機圖形的角度來看待這種情況。首先,我們用畫素組成的平面代替我們的眼睛。在這種情況下,發射的光子將撞擊圖形平面上許多畫素的一個,並將該點的亮度增加到大於零的值。重複多次直到所有的畫素被調整,建立一個計算機生成的影象。這種技術稱為前向光線追蹤(Forward Tracing),因為我們是沿著光子從光源向觀察者的前進的路徑。


但是,這種技術在計算機中模擬光子與物體相互作用是不太現實的,因為在實際中反射的光子擊中眼睛表面的可能性是非常非常低的,我們必須投射大量的光子才能找到一個能夠引起眼睛注意的。此外,我們也不能保證物體的表面被光子完全覆蓋,這是這項技術的主要缺點。

換句話說,我們可能不得不讓程式一直執行,直到足夠的光子噴射到物體的表面上獲得精確的顯示。這意味著我們要監視正在呈現的影象以決定何時停止應用程式。這在實際生產環境中是不可能的。另外,正如我們將看到的,射線追蹤器中最昂貴的任務是找到射線幾何交點。從光源產生大量光子不是問題,但是在場景內找到所有的交點將會是非常昂貴的。

2、Backward Tracing

這項技術為前向光線追蹤技術的缺陷提供了一個方便的解決方案。由於我們的模擬不能像自然一樣快速完美,所以我們必須妥協,並追蹤從眼睛進入到場景中的光線。

光線照到一個物體時,我們可以通過將另一條光線(稱為光線或陰影光線)從擊中點投射到場景的光線,得到它所接受到的光子數量。這個“光線”有的時候會被另一個物體阻擋,這意味著我們原來的撞擊點在陰影中,沒有獲得任何照明。


三、演算法實現

1、基本原理
  • 光線追蹤演算法採用由畫素組成的影象。對於影象中的每個畫素,它將主光線投射到場景中。該主光線的方向是通過追蹤從眼睛到畫素中心線獲得的。一旦我們確定了主射線的方向,我們就開始檢查場景中的每個物件,看它是否與其中的任何一個相交。當發生主射線與多個物件相交的情況時,我們選擇交點離眼睛最近的物體。
  • 然後,我們從交叉點向光線投射陰影射線。如果這條特定的光線在通往光源的路上不與某個物體相交,那麼這個點就被照亮了。
  • 如果它與另一個物體相交,則該物體在其上投下陰影。
  • 最後,如果我們對每個畫素重複這一操作,就可以獲得三維場景的二維表示。
2、虛擬碼

光線追蹤演算法實現的虛擬碼如下所示:

for (int j = 0; j < imageHeight; ++j) { 
    for (int i = 0; i < imageWidth; ++i) { 
        // compute primary ray direction
        Ray primRay; 
        computePrimRay(i, j, &primRay); 
        // shoot prim ray in the scene and search for intersection
        Normal nHit; 
        float minDist = INFINITY; 
        Object object = NULL; 
        for (int k = 0; k < objects.size(); ++k) { 
            if (Intersect(objects[k], primRay, &pHit, &nHit)) { 
                float distance = Distance(eyePosition, pHit); 
                if (distance < minDistance) { 
                    object = objects[k]; 
                    minDistance = distance; // update min distance 
                } 
            } 
        } 
        if (object != NULL) { 
            // compute illumination
            Ray shadowRay; 
            shadowRay.direction = lightPosition - pHit; 
            bool isShadow = false; 
            for (int k = 0; k < objects.size(); ++k) { 
                if (Intersect(objects[k], shadowRay)) { 
                    isInShadow = true; 
                    break; 
                } 
            } 
        } 
        if (!isInShadow) 
            pixels[i][j] = object->color * light.brightness; 
        else 
            pixels[i][j] = 0; 
    } 
} 

四、加入反射和折射

1、基本原理

在光學中,反射和折射是總所周知的現象。反射和折射分向都是基於相交點處的法線和入射光線(主光線)的方向。為了計算折射方向,我們還需指定材料的折射率。

同樣,我們也必須意識到像玻璃球這樣的物體同時具有反射性和折射性的事實。我們需要為表面上的給定點計算兩者的混合值。反射和折射具體值的混合取決於主光線(或觀察方向)和物體的法線和折射率之間的夾角。有一個方程式精確地計算了每個應該如何混合,這個方程被稱為菲涅耳方程。

加入反射折射後,進行以下三個步驟:

  • 計算反射
為此,我們需要兩個項:交點處的法線和主光線的方向。一旦我們獲得了反射方向,我們就朝這個方向發射新的光線。我們假設反射光線撞擊了紅色球體,通過向光線投射陰影射線來找出到達紅色球體上的那個點的光線多少。這會得到一種顏色(如果是陰影,則為黑色),然後乘以光強並返回到玻璃球的表面。
  • 計算折射

注意,因為光線穿過玻璃球,所以它被認為是透射光線(光線從球體的一側傳播到另一側)。為了計算透射方向,我們需要在知道擊中點的法線,主射線方向和材料的折射率。

當光線進入並離開玻璃物體時,光線的方向會改變。每當介質發生變化時都會發生折射,而且兩種介質具有不同的折射率。折射對光線有輕微彎曲的作用。這個過程就是讓物體在透視時或在不同折射率的物體上出現偏移的原因。

現在讓我們想象一下,當折射的光線離開玻璃球時,它會碰到一個綠色的球體。在那裡,我們再次計算綠色球體和折射射線之間交點處的區域性照明(通過拍攝陰影射線)。然後,將顏色(如果被遮擋,則為黑色)乘以光強並返回到玻璃球的表面。

  • 應用菲涅爾方程

我們需要玻璃球的折射率,主光線的角度,以及擊中點的法線。使用點積,菲涅耳方程返回兩個混合值。


這種演算法的美妙之處在於它是遞迴的。迄今為止,在我們研究過的情況下,反射光線照射到一個紅色的、不透明的球體上,而折射光線照射到一個綠色的、不透明的和漫射的球體上。但是,我們會想象紅色和綠色的球體也是玻璃球。為了找到由反射和折射光線返回的顏色,我們必須按照與原始玻璃球一起使用的紅色和綠色球體的相同過程。

這是光線追蹤演算法的一個嚴重缺陷。想象一下,我們的相機是在一個只有反射面的盒子裡。從理論上講,光線被困住了,並且會持續不斷地從箱子的牆壁反彈(或者直到你停止模擬)。出於這個原因,我們必須設定一個任意的限制值,從而防止光線相互作用導致的無限遞迴。每當光線反射或折射時,其深度都會增加。當光線深度大於最大遞迴深度時,我們就停止遞迴過程。

2、虛擬碼

虛擬碼如下所示:

// compute reflection color
color reflectionCol = computeReflectionColor(); 
// compute refraction color
color refractionCol = computeRefractionColor(); 
float Kr; // reflection mix value 
float Kt; // refraction mix value 
fresnel(refractiveIndex, normalHit, primaryRayDirection, &Kr, &Kt); 
// mix the two
color glassBallColorAtHit = Kr * reflectionColor + (1-Kr) * refractionColor; 

五、參考文獻

英文:http://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-ray-tracing

原始碼:http://www.scratchapixel.com/code.php?id=3&origin=/lessons/3d-basic-rendering/introduction-to-ray-tracing

相關推薦

計算機圖形——光線追蹤RayTracing演算法

前言最近處於畢設答辯前的空檔期,沒什麼要緊的事情要做,於是空閒之餘隨意看了下點計算機圖形學,學習了一個畫3D圖形的光線追蹤演算法,在此簡單地分享一下~一、理論基礎1、三維場景中建立影象第一步:透視投影。這是一個將三維物體的形狀投影到影象表面上的幾何過程,這一步只需要連線從物件

計算機圖形 學習筆記:概述,直線掃描轉換演算法:DDA,中點畫線演算法,Bresenham演算法

前言 感謝中國農大 趙明老師的分享~ 現在我要為我自己走向遊戲程式設計打下基石~ 1 計算機圖形學概論 1.1 計算機圖形學課程簡介 《計算機圖形學》是計算機、地理資訊系統、應用數學、機械、建築等專業本科教學中的一門重要的專業基礎課 如影

計算機圖形 學習筆記:二維圖形變換:平移,比例,旋轉,座標變換等

在圖形學中,有兩大基本工具:向量分析,圖形變換。本文將重點講解向量和二維圖形的變換。 5.1 向量基礎知識 我們所使用的所有點和向量都是基於某一座標系定義的,比如左手座標系或者右手座標系。 從幾何的角度來看,向量是具有長度和方向的實體,但是沒有

計算機圖形 讀書筆記 基礎概念

寫個讀書筆記,一來作為字典以後可以查,二來記錄自己的理解。並沒有對每個知識點的詳細解釋,大部分只有主觀的定性的解釋。大量的配圖用的清華大學的PPT裡的圖,會不會有版權問題呀。。。。讓我刪我就刪。。一、顏色一種特定顏色的光可以由一種光譜表示,但這種表示方法太複雜,所以產生了其他

計算機圖形 學習筆記:多邊形掃描轉換:X掃描線演算法 和 改進的X掃描線演算法

光柵圖形學演算法 2.4 多邊形掃描轉換-X掃描線演算法 多邊形的掃描轉換和區域填充這個問題是怎麼樣在離散的畫素集上表示一個連續的二維圖形? 多邊形有兩種重要的表示方法:頂點表示和點陣表示 頂點表示 頂點表示是用多邊形的頂點序列來表

計算機圖形學習記錄Breseham畫線演算法

Breseham演算法 首先為了方便直接看演算法程式碼的朋友直接看核心程式碼和結果,在這裡直接貼出演算法程式碼。 void DDADrawLine::BreasehamDrawLine(int x0, int y0, int x1, int y1) {

清華髮布:2018計算機圖形研究報告附下載

導讀:報告包括概述篇、技術篇、人才篇、會議篇、應用篇、趨勢篇,本文擷取概述篇部分內容。在公眾號後

計算機圖形 學習筆記十二:顏色模型,簡單 / 增量 光照模型

接下來將介紹真實感圖形學的內容。 真實感圖形學包括:顏色模型,簡單光照模型,增量光照模型,區域性光照模型和投射模型,整體光照模型,紋理對映和陰影處理。 真實感圖形學 真實感圖形學研究的是什麼?簡單來說,就是希望用計算機生成像照相機拍的照片一樣逼真地

圖形學習總結—背面消除

物體從區域性座標最後渲染到螢幕上我們已經基本瞭解了,但是在3d流水線中還有一些操作是需要的,就是物體的背面消除和剔除,可以避免大量無用的運算 背面消除 物體的背面消除很簡單,在世界座標中進行,即相機座標轉換操作之前,物體的面法量與面到視點的向量的夾角不超過90度時,這個面

[圖形] 光線追蹤中的數學方法

reference: 《Mathematics for 3D Game Programming and Computer Graphics》 目錄 6.1 求根    6.1.1 二次多項式    6.1.2 三次多項式    6.1.3 四次多項式    6.1.4 牛

計算機圖形筆記-三種畫線演算法

1.DDA:在一個座標軸上以單位間隔對線段取樣,從而確定另一個座標軸上最靠近路線的整數點。 如果斜率m<=1,則以單位X間隔取樣,逐步計算y值 y(k+1)=y(k)+m 如果斜率m>1,則以單位Y間隔取樣,逐步計算X值 x(k+1)=x(k)+

計算機圖形 視頻顯示設備_1_CRT原理

http color size 安裝 ref p s 這一 計算機圖形學 指定 第 1 章 圖形系統概述 如今。計算機圖形學的作用與應用已經得到了廣泛承認。大量的圖形硬件和軟件系統已經應用 到了差點兒全部的領域。通用計算機甚至很多手持計算器也已經

MFC計算機圖形2

mct tid spc DdGzS cin html uem ubd dcs sdsdzi狗聘毫渤口毫http://huiyi.docin.com/hnbkw203d1e5gw濫良瘟侍探蝗http://weibo.com/p/10050563731520645atr4g回救

計算機圖形輸出圖元_3_畫線算法_2_DDA算法

通過 程序 之間 tro 取整 xen git 方程 class DDA算法? ? ? ? 數字微分分析儀(digital differential analyzer, DDA)方法是一種線段掃描轉換算法。基於使用等式(3

計算機圖形第2版 於萬波 於碩 編著第45頁的Bresenham算法有錯誤

str mage mov 步長 分享圖片 圖片 方法總結 tro 計算 計算機圖形學(第2版 於萬波 於碩 編著)第45頁的Bresenham算法有錯誤: 書上本來要寫的是以x為階越步長的方法,但是他寫的是用一部分y為階越步長的方法(其實也寫的不對),最後以x為階越

計算機圖形三種畫線算法

直線 情況 算法 n) src 隨著 多邊形 取整 兩個 第二章:光柵圖形學算法 1、光柵顯示器:光柵掃描式圖形顯示器簡稱光柵顯示器,是畫點設備,可看作是一個點陣單元發生器,並可控制每個點陣單元的亮度 2、由來:隨著光柵顯示器的出現,為了在計算機上處理、顯示圖形,需要發展一

讀書筆記——計算機圖形基礎OpenGL版第一章

mat 線框 設備 框圖 展示 關系 模型 設計 pan 第一章緒論 本章主要內容 : 計算機圖形學的目標和任務計算機圖形學的內容體系計算機圖形學的相關學科計算機圖形學的應用領域計算機圖形學的發展 一、CG的目標 核心目標:視覺交流,通過圖形或幾何的方式來表示或展示

計算機圖形OpengGl版 實驗

結果展示: #include <windows.h> #include <GL/glut.h> #include <stdlib.h> #include <bits/stdc++.h> using namespace std; vo

計算機圖形實驗--直線DDA演算法的實現

1. DDA演算法(數值微分法)原理:     1)網上或者計算機圖形學書本上有詳細介紹。     2)最核心的是選定(x2-x1)和(y2-y1)中較大者為步進方向。 2. 實現工具:     1) VS2017(C++)

計算機圖形實驗—— 直線Bresenham演算法原始碼

 1. Bresenham演算法核心:(詳細原理見末尾) 理解光柵化:畫素點只能是整數點。 藉助決策變數 的正負號判斷下一個點座標,從而避免了計算直線斜率所用乘除法,只需要用加減法。 預設斜率絕對值在區間(0,1)時,即abs(dx)>abs(dy),步進方