體散射初步

2022-03-13 19:50:59 字數 2835 閱讀 9613

在說體散射之前有必要先說說渲染方程(rendering equation),這個著名的方程是kajiya在2023年提出來的,其基本形式為:

這其中lo(x,w)表示是在點x及出射角度w上的出射光強度,le表示在點x及出射角度

上的自發光強度,隨後的一段積分則表示從外部環境中各個方向上到達點x的光強的總量。通俗地說就是:"場景中某一點的光強等於該點的自發光強度(一般光源才有自發光)加上從場景中其他點通過反射(折射)到達該點的光強"。渲染方程描述了光能在場景中的流動過程,而之前的各種全域性光照和區域性光照演算法都是對該方程的乙個近似求解。渲染方程的出現標誌著全域性光照的發展進入乙個全新的時代,可以做出越來越逼真的效果。然而它本身也是有侷限的,因為它只考慮了幾何光學部分,無法表現光的衍射,干涉,偏振,色散等物理現象,也不能模擬自然界中螢光和磷光等現象。不僅如此,在一般場景中,該模型也忽略了乙個重要的事實:在場景中各個物體之間也是存在物質的,它們也可能和光發生作用。

一般而言,場景中物體之間充滿著空氣,有限體積的空氣和光的作用可以忽略不計,但是若場景中充滿了微粒(比如灰塵),那麼這個對光傳播的影響就不容小視了。公尺氏散射從物理上定義了這種光散射現象:當微粒半徑的大小接近於或者大於入射光線的波長λ的時候,大部分的入射光線會沿著前進的方向進行散射,這種現象被稱為公尺式散射。這種大微粒包括灰塵,水滴,來自汙染物的顆粒物質,如煙霧,等等(wiki上的解釋)。還有一種情況,就是當微粒的半徑足夠小(小於0.1λ),散射光線的強度與入射光線波長的四次方成反比,因此對於較短波長的散射程度要遠遠大於較大波長,這種散射被稱為瑞利散射。瑞利散射也解釋了為什麼在雨過天晴或者秋高氣爽的時候,天空呈現蔚藍。因為這個時候空氣中較粗微粒比較少,青藍色光的散射顯得更為突出。

為了模擬公尺氏散射現象(比如充滿灰塵的房間或者大霧瀰漫的街道),我們必須知道一些重要的資料,這包括介質的密度,這裡的介質不一定是密度均勻的,所以我們必須知道介質各處的密度函式,而這樣的體資料是比較難找的,所以一種簡化的模型就是假設介質各處密度相同,這就是常說的體積霧。除了介質密度外,吸收率σa和散射率σs引數也很重要,它們決定了介質對光的吸收和散射程度。相位函式p(θ)決定了當光在介質中發生散射的時候,向各個方向散射的概率。相位函式其實是乙個概率密度函式,因此各個方向上機率之和要等於一。最簡單的相位函式是各向同性散射函式,也就是說光朝任意方向散射的概率都是相等的。更為複雜的有henyey-greenstein函式,以及schlick函式,它們的特點是,散射方向以接近光原來的前進方向和其反方向的居多,而往與光前進方向垂直平面上散射的概率最小。有了這些引數後,我們可以使用ray marching來模擬體散射。下面講一下ray marching方法。

ray marching與ray tracing有所不同,在於前者不像後者發出射線找到交點後就直接計算交點光照,ray marching要考慮整個中間傳播過程,它將整個傳播過程沿途分段取樣,將取樣得到的資料乘以當前衰減係數後相加作為最終光強。下圖展示了ray marching的計算過程:

圖中由ray tracing定位到射線與球面的交點,計算出顏色color-sphere,然後沿整個射線路徑取到6個點,分別計算這6個點上介質的顏色值(color1 - color6),最後將它們分別乘以各自的衰減係數後相加得到最終顏色值。可以用如下公式概括說明這個計算過程:

,在上面例子中n=7,color7=color-sphere,ki是各自的衰減係數。在ray marching中一般每取樣一次,就在之前的基礎上乘上乙個衰減值,這個衰減值就是介質的吸收率σa和散射率σs之和:σt=σa+σs,這也符合朗伯比爾定律對光穿過介質的描述,即在均勻介質中,透射比t的對數和介質厚度的相反數成正比。更通俗地說,就是在介質中,光強是按照傳播距離指數衰減的。有了這一點,我們能更加方便地求出每個點的衰減係數,假定ray marching的取樣步長取為s的話,毫無疑問光在傳播了距離s後強度衰減為原來的(1-σt),而在傳播了任意距離l後,則衰減後的值可以由(1-σt)(l/s)得到,這個公式在ray marching反走樣中也會用到,因為效率原因取樣步長s不可能取到太小,這時,可以在s的基礎上新增隨機擾動,使每一次的步長不一樣,那麼衰減後的值也可以由公式(1-σt)(l/s)得到。需要提醒一點的是(1-σt)(l/s)僅僅是乙個近似公式,這是因為步長s是乙個有限值,現實中光在介質中傳播的時候並不是每經過s距離才衰減一次,而是無時無刻不在衰減,也就是說s是趨於0的,朗伯比爾定律給出該模型的精確值:e-σtl。

對於ray marching每一步取樣點的顏色值colori該如何計算呢?對於均勻介質而言,可以從光源向該點作射線,然後得到射線需要穿過介質的厚度,代入到之前的衰減值公式中求出衰減後的光源光強乘以介質本身的顏色就可以了。但是這樣做有乙個很大的問題是沒有考慮到介質本身的散射,因為介質中某一點的光強不僅僅來自於光源,還可以來自介質中其他點的散射,也可以來自於場景中其他實體的漫反射。在這裡,我用的是光子對映來模擬這種多重散射現象。從光源發出的光子可以在介質中被多次散射,每次散射和吸收的時候都會被記錄下來,為了方便使用光子圖,體散射光子應該和全域性光子分開儲存,這樣也可以加快計算的效率。體散射光子密度估計的蒐集過程是用的乙個標準球體來蒐集的,而之前的是用的半球,碟形蒐集等。下面幾幅圖展示了體積霧的效果:

c 入門之結構體初步

結構體實際上是一種資料結構的雛形,對結構體的靈活使用很多時候可以帶來很多便利.下面給出乙個關於結構體的程式 1 include iostream 2 include cmath 3 struct polar4 8struct rect9 13void rect to polar rect pa,po...

物聯網之散射通訊應用

散射通訊指利用大氣層中傳播媒介的不均勻性對無線電波的散射作用進行的超短波 微波超視距通訊。根據散射媒質的不同,散射通訊一般分為對流層散射通訊和電離層散射通訊,本文描述對流層散射通訊。散射通訊系統單跳跨距遠 抗毀 抗擾和抗截獲能力強,具有跨越山丘 海灣 沙漠等複雜地形可靠通訊等特點。散射通訊採用多模傳...

子彈散射 Unity隨手記(2021 2 4)

bug以及缺陷 值得注意的 子彈散射邏輯 子彈散射就相對後坐力簡單多了。在createbullet的時候給予子彈乙個隨機大小的角度偏量。計算子彈散射量 protected vector3 calculatebulletspreadoffset 這是散射演算法,使用unity的insideunitci...