網(wǎng)上有很多關(guān)于t1天到賬的pos機(jī),游戲中迷人天空的顏色是如何制作出來的的知識(shí),也有很多人為大家解答關(guān)于t1天到賬的pos機(jī)的問題,今天pos機(jī)之家(www.tjfsxbj.com)為大家整理了關(guān)于這方面的知識(shí),讓我們一起來看下吧!
本文目錄一覽:
t1天到賬的pos機(jī)
以下文章來源于騰訊游戲?qū)W院 ,作者spaceoddity42
騰訊游戲?qū)W院由騰訊互動(dòng)娛樂發(fā)起,致力于打造游戲知識(shí)分享和交流平臺(tái),專注建設(shè)游戲職業(yè)培訓(xùn)和發(fā)展體系。學(xué)院通過提供游戲類專業(yè)培訓(xùn)課程、建設(shè)游戲職業(yè)發(fā)展通道、開展豐富的校園活動(dòng)及行業(yè)活動(dòng),幫助在校生和游戲從業(yè)者提升職業(yè)競(jìng)爭(zhēng)力,成就游戲創(chuàng)想夢(mèng)。
轉(zhuǎn)載請(qǐng)注明文章來源于騰訊游戲?qū)W院
文丨spaceoddity42 騰訊互動(dòng)娛樂 工程師
幾個(gè)世紀(jì)以來,天空一直是許多藝術(shù)家迷戀的主題,他們?cè)噲D盡可能準(zhǔn)確地描繪其顏色。同樣的,在游戲開發(fā)中,天空渲染對(duì)于游戲開發(fā)者也一直是一個(gè)迷人的主題,本文理論部分譯自scratchapixel,介紹了天空渲染的理論基礎(chǔ),并在此基礎(chǔ)上了建立相應(yīng)的數(shù)學(xué)模型,最后在ShaderToy上通過Pixel Shader來實(shí)現(xiàn)相應(yīng)的算法。
本章我們將學(xué)習(xí)大氣散射,推薦先閱讀體積渲染和次表面散射的內(nèi)容(詳見www.scratchapixel.com),它們和本主題包含類似的概念,大氣散射可以看作是體積渲染的擴(kuò)展。
1、大氣散射的理論基礎(chǔ)
1.1 介紹
幾個(gè)世紀(jì)以來,天空一直是許多藝術(shù)家迷戀的主題,他們?cè)噲D盡可能準(zhǔn)確地描繪其顏色。在19世紀(jì)到20世紀(jì)之前,許多物理學(xué)家和數(shù)學(xué)家癡迷于弄清楚是什么導(dǎo)致天空在日落和日出時(shí)呈現(xiàn)橙色,白天呈現(xiàn)藍(lán)色。從歷史上看,大氣散射的發(fā)現(xiàn)歸功于瑞利(又名John Strutt,獲得諾貝爾獎(jiǎng)的英國(guó)物理學(xué)家),其主要工作是在19世紀(jì)產(chǎn)生的(瑞利接替了劍橋大學(xué)的麥克斯韋,后者因其在電磁方面的貢獻(xiàn)而聞名,計(jì)算機(jī)圖形很大一部分的研究與麥克斯韋的工作有關(guān),瑞利還和普朗克研究了黑體)。大氣散射也會(huì)對(duì)物體的外觀產(chǎn)生影響,這種效應(yīng)被稱為空氣透視(繪畫中多稱為大氣透視),被萊昂納多達(dá)芬奇首次觀察、研究和應(yīng)用在他的畫作中(事實(shí)上,這種技術(shù)可以在達(dá)芬奇作品之前的繪畫作品中找到)。隨著物體和觀察者之間的距離增加,物體的顏色被大氣的顏色所取代(對(duì)于天空來說,它通常在白天呈現(xiàn)藍(lán)色,日出和日落時(shí)呈現(xiàn)紅橙色)。這是一個(gè)重要的視覺線索,因?yàn)槿藗兺ㄟ^比較它們相對(duì)于彼此有多藍(lán)來判斷場(chǎng)景中物體的距離。在(數(shù)字)繪畫中,空氣透視可以極大地幫助增加圖像的深度(大腦可以更容易地處理比另一個(gè)更遠(yuǎn)的物體),如下為達(dá)芬奇畫作復(fù)制品(注意后面的巖石的顏色受到大氣的影響)。
在計(jì)算機(jī)圖形學(xué)史上,Nishita在1993年發(fā)表了一篇開創(chuàng)性的論文”Display of the Earth Taking into account Atmospheric Scattering”,他在這篇論文中描述了一種模擬天空顏色的算法,有趣的是他的這篇論文和他在1996年寫的關(guān)于同一主題的另一篇論文"Display Method of the Sky Color Taking into Account Multiple Scattering"不完全是關(guān)于大氣模擬,更多是關(guān)于從外太空看到的地球的真實(shí)渲染(包括渲染海洋表面、云層和大陸)。
Figure 1: Top, a real photograph of the Earth from outer space. Bottom, a simulation using Nishita's model. These images have been copied from the paper "Display of the Earth taking into account Atmospheric Scattering" written by Nishita in 1993 (c) Siggraph.
這提醒了我們?cè)谶@些年里,計(jì)算機(jī)圖形技術(shù)的發(fā)展是由制造業(yè)推動(dòng)的,用于精確模擬其產(chǎn)品或提供3D虛擬訓(xùn)練環(huán)境,而不是娛樂行業(yè)(電影和游戲)。Nishita描述的模擬天空的技術(shù)從他的時(shí)代以來沒有太大變化,在該領(lǐng)域的大部分研究都集中在GPU上實(shí)現(xiàn)Nishita的算法,而模擬質(zhì)量沒有任何明顯改善(更多關(guān)注的是速度和實(shí)時(shí)仿真)。在1999年發(fā)表于Siggraph的一篇論文”A Practical Analytic Model for Daylight”中,Preetham等人描述了另一種天空模型,正如其標(biāo)題所示,這是一個(gè)分析模型,它提供了對(duì)天空顏色的精確模擬,但它比Nishita提出的技術(shù)有更多限制(例如,該模型僅適用于位于地面上的觀察者)。值得一提的是Jensen等人在2011年Siggraph上發(fā)表的一篇模擬夜空的論文”A Physically-Based Nightsky Model”,本章將給出Nishita模型的實(shí)現(xiàn)。
在后面小節(jié)中,我們將描述各種現(xiàn)象,它們組合在一起呈現(xiàn)天空的顏色,然后我們將展示Nishita的算法如何模擬這些現(xiàn)象,一旦我們?cè)诔绦蛑袑?shí)現(xiàn)了該模型,我們可以輕松擴(kuò)展該技術(shù)以模擬空氣透視,通過改變模型的參數(shù),我們還可以創(chuàng)建外星天空。
1.2 大氣模型
大氣層是行星周圍的一層氣體,由于行星的引力,大氣層保持在適當(dāng)?shù)奈恢茫髿鈱拥闹饕P(guān)注點(diǎn)是它的厚度和成分(組成大氣層的不同成分)。地球大氣層厚度約為100km(由卡門線劃定,卡門線是公認(rèn)的外太空與地球大氣層的分界線),它由氧氣、氮?dú)狻鍤猓ㄈ鹄l(fā)現(xiàn)的氣體)、二氧化碳和水蒸氣組成。然而,在模擬中,我們將使用60km的厚度(我們只考慮在地球大氣的前兩層,對(duì)流層和平流層中的散射)。如果你閱讀有關(guān)體積渲染的內(nèi)容(建議首先看這部分內(nèi)容再來看本篇內(nèi)容),你將知道光子在與粒子碰撞時(shí)會(huì)散射。當(dāng)光在某個(gè)方向上穿過一個(gè)體積(大氣)時(shí),光子在與粒子碰撞時(shí)會(huì)往其他方向上偏轉(zhuǎn),這種現(xiàn)象稱為散射。光被粒子散射的頻率取決于粒子的性質(zhì)(主要是它們的大?。┖退鼈兊拿芏龋▎挝惑w積中有多少粒子/分子)。我們現(xiàn)在已經(jīng)知道了地球大氣層的分子大小,我們也知道它們的濃度/密度。我們將使用這些科學(xué)測(cè)量數(shù)據(jù)來進(jìn)行大氣散射模擬。地球周圍大氣層的另一個(gè)重要方面是這些顆粒的密度隨高度的增加而減小。換句話說,比如在海平面上每單位立方體空氣中的分子比海洋上方2公里多。這是一個(gè)重要的事實(shí),因?yàn)樯⑸淞咳Q于我們剛剛提到的分子密度。當(dāng)光在大氣層中從上層傳播到地面時(shí),我們需要沿著光線按固定間隔對(duì)大氣密度進(jìn)行采樣,并根據(jù)這些樣本位置處的大氣密度計(jì)算散射量(我們將使用數(shù)值積分,下一步會(huì)詳細(xì)解釋)。大多數(shù)論文(包括Nishita的論文)都假設(shè)大氣密度隨高度呈指數(shù)下降。換句話說,它可以用以下形式的簡(jiǎn)單方程建模:
其中density(0)是海平面的空氣密度,h是我們測(cè)量大氣密度時(shí)的高度(海拔高度),H是大氣密度均勻時(shí)的大氣厚度(在科學(xué)論文中,H被稱為大氣標(biāo)高,大氣密度每經(jīng)過一段距離H其值就減少為原來的值的1/e,H取決于溫度)。一些論文聲稱這個(gè)模型是一個(gè)很好的近似,但是其他一些人聲稱它不準(zhǔn)確,并且更喜歡將天空密度模擬為一系列同心層,每個(gè)同心層由它們的厚度和密度決定。(論文出處未知)
將天空密度建模為一系列層(在Nishita的論文中稱為球殼)從計(jì)算的角度來看具有優(yōu)勢(shì)。由于我們將沿著光線朝著觀察者的路徑執(zhí)行數(shù)值積分,在密度高的大氣中采集的樣本比在密度低的情況下采集的樣本更重要,因此沿著光線執(zhí)行“固定步長(zhǎng)”積分將導(dǎo)致收斂性差。如今計(jì)算機(jī)速度如此之快以至于我們可以通過固定步長(zhǎng)來強(qiáng)制執(zhí)行此計(jì)算,但在Nishita那個(gè)時(shí)候,優(yōu)化算法是必要的。因此,Nishita提出了一個(gè)模型,其中大氣層用一系列球形殼體表示,在低海拔使用較小間隔,在高海拔使用較長(zhǎng)間隔。但請(qǐng)注意,在論文中發(fā)表的圖表中,層的厚度似乎非常像按指數(shù)形式變化的,這并不令人驚訝,因?yàn)槊總€(gè)殼的半徑在Nishita的模型中由空氣分子的密度分布精確確定。
大氣層由小顆粒(空氣分子)組成,小顆粒也會(huì)在低空與較大的顆粒混合,稱為氣溶膠。這些顆粒可以是由風(fēng)揚(yáng)起的灰塵或沙子,也可以是因?yàn)榭諝馕廴径嬖诘娜魏晤w粒。它們肯定會(huì)對(duì)大氣的外觀產(chǎn)生影響,特別是因?yàn)樗鼈儾幌窨諝夥肿幽菢由⑸涔饩€。空氣分子對(duì)光的散射稱為瑞利散射,氣溶膠對(duì)光的散射稱為米氏散射。
Figure 2: aerosols present in the atmosphere are responsible for haze.
簡(jiǎn)而言之,瑞利散射(空氣分子散射光)是造成天空藍(lán)色(以及日出和日落時(shí)的紅橙色)的原因,而米氏散射(氣溶膠散射光)通常是造成污染城市上方白灰色霧霾的原因(陰霾掩蓋了天空的清晰度,見圖2)。如果沒有提到使用者需要指定行星和天空的半徑,模型將是不完整的,這些數(shù)字將用于計(jì)算沿觀察者和光線方向上樣本位置的高度。對(duì)于地球,我們將使用Re = 6360 km(e代表地球)和Ra = 6420 km(a代表大氣層)。該模型中與距離相關(guān)的所有距離和參數(shù)應(yīng)在同一單位系統(tǒng)中表示(km、m等)。
Figure 3: a simple graphical representation of the atmospheric model we will be using in this lesson. It is defined by the radius of the planet (Re) and the radius of the atmosphere (Ra). The atmosphere is made of aerosols (mainly present at low altitude) and air molecules. Density of particles decreases exponentially with altitude. This diagram is not to scale.
對(duì)于大氣模型,這可能是棘手的,因?yàn)樾行堑拇笮】赡芎艽蟆?duì)于這樣的尺寸,公里通常是更合適的選擇。然而,散射系數(shù)非常小,并且它們更容易用米或毫米(對(duì)于光波長(zhǎng)甚至用納米)來表示。選擇一個(gè)好的單位也是因?yàn)楦↑c(diǎn)數(shù)精度的限制(也就是說,如果數(shù)字太大或太小,計(jì)算機(jī)對(duì)這些數(shù)字的浮點(diǎn)表示可能會(huì)變得不準(zhǔn)確,從而導(dǎo)致計(jì)算錯(cuò)誤)。模型的輸入?yún)?shù)可以用不同的單位表示,并由程序內(nèi)部轉(zhuǎn)換。
最后,我們通過指定天空的主要照明來源是太陽(yáng)這一點(diǎn)來完成我們對(duì)模型的描述,太陽(yáng)離地球太遠(yuǎn),我們可以假設(shè)所有到達(dá)大氣層的光線都是相互平行的,我們將進(jìn)一步展示這種假設(shè)如何簡(jiǎn)化模型的實(shí)現(xiàn)。
Figure 4: the sun is so far away from the Earth, that each light ray reaching the Earth's atmosphere can be considered as being parallel to each other.
1.3 瑞利散射
瑞利在19世紀(jì)晚期發(fā)現(xiàn)了空氣分子對(duì)光的散射。他特別指出,這種現(xiàn)象具有強(qiáng)烈的波長(zhǎng)依賴性,更準(zhǔn)確地說,空氣分子散射的藍(lán)光比綠光和紅光更多(ps:更容易散射藍(lán)光)。這種形式的散射和他提出的計(jì)算由分子(例如我們?cè)诖髿庵姓业降姆肿樱┙M成的體積的散射系數(shù)的方程,僅適用于尺寸遠(yuǎn)小于構(gòu)成可見光的波長(zhǎng)的顆粒(粒子應(yīng)至少比散射波長(zhǎng)小十分之一)??梢姽獾牟ㄩL(zhǎng)在380到780 nm之間變化,440,550和680分別被認(rèn)為是藍(lán)色,綠色和紅色光的波長(zhǎng)峰值,我們將在本文的其余部分使用這些值。瑞利散射方程提供了計(jì)算已知分子密度的體積的散射系數(shù)。在關(guān)于大氣散射的文獻(xiàn)中,散射系數(shù)由希臘字母β(beta)表示。
上標(biāo)S用于標(biāo)識(shí)散射,下標(biāo)R用于標(biāo)識(shí)瑞利(用于將這些系數(shù)與米氏散射系數(shù)區(qū)分開)。在這個(gè)等式中,h是高度,λ是波長(zhǎng),N是海平面的分子密度,n是空氣的折射率,是大氣標(biāo)高。在我們的模擬中,我們將使用=8km(如果需要,請(qǐng)參見網(wǎng)上的大氣標(biāo)高以獲得更精確的測(cè)量數(shù)據(jù))。正如你所看到的,具有短波長(zhǎng)的光(例如藍(lán)光)的β值比長(zhǎng)波長(zhǎng)的光(紅色)更高,這解釋了白天天空呈現(xiàn)藍(lán)色的原因。當(dāng)來自太陽(yáng)的光穿過大氣層時(shí),相比綠色和紅色光,藍(lán)色光更多地向觀察者散射。為什么在日出和日落時(shí)會(huì)出現(xiàn)紅橙色?在此種情況下(日出、日落時(shí)),相比于太陽(yáng)高于頭部(天頂位置)時(shí),來自太陽(yáng)的光必須在大氣層中行進(jìn)更長(zhǎng)部分以到達(dá)觀察者的位置。那距離相當(dāng)長(zhǎng),大部分藍(lán)光在到達(dá)觀察者的位置之前已經(jīng)散開,而一些不像藍(lán)光一樣散射的紅光仍然存在。因此,日出和日落時(shí)的天空呈現(xiàn)紅橙色(有時(shí)可以是紫色或略帶綠色)。我們可以使用一個(gè)N,n的測(cè)量值來計(jì)算β,但是我們將使用在海平面的散射系數(shù)的預(yù)計(jì)算值(波長(zhǎng)440、550和680nm,對(duì)應(yīng)的散射系數(shù)分別是:
、
、
,注意藍(lán)光的散射系數(shù)大于綠光和紅光的散射系數(shù))。通過應(yīng)用方程的指數(shù)部分(右項(xiàng)),我們可以調(diào)整任何給定高度h的這些系數(shù)。
Nishita的論文和我們?cè)诒酒刑岬降钠渌撐牡闹饕獑栴}之一是他們要么沒有給出N,n等的值來生成論文中顯示的圖像。在使用測(cè)量數(shù)據(jù)時(shí),論文的作者通常不會(huì)引用它們的來源。在海平面上尋找分子密度的科學(xué)數(shù)據(jù)并不容易,如果你有任何關(guān)于此主題的有用鏈接或信息,你可以向我們提供,我們希望收到你的來信。我們?cè)诒酒惺褂玫暮F矫嫔⑸湎禂?shù)可以在兩篇論文中找到:"Efficient Rendering of Atmospheric Phenomena", by Riley et al. and "Precomputed Atmospheric Scattering" by Bruneton et al.
我們不會(huì)詳細(xì)介紹空氣密度,但可以在互聯(lián)網(wǎng)上找到有關(guān)此問題的有趣信息。在本篇中,我們真正需要的是海平面的平均散射系數(shù),它們可以很好地重建天空的顏色,但是學(xué)習(xí)如何計(jì)算這些系數(shù)將會(huì)讓任何想要更好地控制大氣模型的好奇讀者感興趣。
如果你閱讀有關(guān)體積渲染的內(nèi)容,你將會(huì)知道用于渲染參與介質(zhì)的物理模型是散射系數(shù),吸收系數(shù)和相函數(shù),它描述光在與粒子碰撞時(shí)散射的程度和方向。到目前為止,在本篇中,我們只給出了地球大氣層的散射系數(shù)值(并解釋了如何計(jì)算)。對(duì)于大氣散射,通常認(rèn)為吸收系數(shù)可忽略不計(jì),換句話說,我們將假設(shè)大氣不吸收光。還記得在體積渲染的內(nèi)容中,我們?cè)阡秩緟⑴c介質(zhì)時(shí)使用的物理模型中需要的衰減系數(shù)是吸收系數(shù)和散射系數(shù)的總和,因此(因?yàn)槲障禂?shù)為零)衰減系數(shù)可以表示為:
瑞利相函數(shù)看起來像這樣:
其中μ是光與視線方向之間角度的余弦(見圖8)。
1.4 米氏散射
米氏散射在某種程度上類似于瑞利散射,但適用于尺寸大于散射波長(zhǎng)的粒子(比如我們?cè)诘厍虼髿鈱拥牡秃0蔚貐^(qū)發(fā)現(xiàn)的氣溶膠)。如果我們將瑞利方程應(yīng)用于氣溶膠,不會(huì)得到令人信服的圖像。渲染散射系數(shù)的米氏方程如下所示:
下標(biāo)M標(biāo)識(shí)米氏散射,注意,對(duì)于米氏散射存在特定的大氣標(biāo)高,其通常設(shè)定為1.2km。與瑞利散射相反,我們不需要方程來計(jì)算米氏散射系數(shù)。我們將使用海平面測(cè)量值來代替。對(duì)于米氏散射,我們將使用:
。氣溶膠的密度也隨著海拔高度呈指數(shù)下降,同瑞利散射類似,我們將通過在方程(由大氣標(biāo)高調(diào)制)的右邊包含一個(gè)指數(shù)項(xiàng)來模擬這種效應(yīng)。米氏相函數(shù)方程是:
米氏相函數(shù)包括控制介質(zhì)各向異性的項(xiàng)g(瑞利相函數(shù)不包括),氣溶膠具有很強(qiáng)的前向指向性,一些論文使用g=0.76(我們也將使用這個(gè)值作為我們的默認(rèn)值)。
1.5 光學(xué)深度的概念
在實(shí)現(xiàn)算法之前,我們將把所有零散部分放在一起。首先,我們應(yīng)該注意到,天空只不過是圍繞實(shí)心球體的球形體積。因?yàn)樗皇且粋€(gè)體積,為了渲染天空,我們可以使用光線步進(jìn)算法,這是最常用的渲染參與介質(zhì)的技術(shù)。我們?cè)陉P(guān)于體積渲染的課程中詳細(xì)研究了該算法。當(dāng)我們渲染一個(gè)體積時(shí),觀察者(或相機(jī))可以在體積內(nèi)部或外部。
當(dāng)相機(jī)在體積內(nèi)時(shí),我們需要找到觀察光線離開體積的點(diǎn),當(dāng)它在體積外時(shí),我們需要找到觀察光線進(jìn)入和離開體積的點(diǎn)。因?yàn)樘炜帐且粋€(gè)球體,我們將使用光線與球體相交測(cè)試的方式來計(jì)算這些點(diǎn)。我們通過使用地面作為參考來測(cè)試相機(jī)位于大氣層內(nèi)部或外部。如果此高度大于大氣厚度,則攝像機(jī)位于大氣層之外,并且觀察光線可能在兩個(gè)地方與大氣層相交。
Figure 6: the camera can either be inside the atmosphere or outside. When it is inside, we are only interested in the intersection point between the camera ray and the atmosphere. When the camera is outside it can intersect the atmosphere in two points.
現(xiàn)在我們假設(shè)攝像機(jī)在地面上(或高出地面一米),但該算法適用于任意攝像機(jī)位置。讓我們假設(shè)我們有一個(gè)觀察光線(對(duì)應(yīng)于幀中的一個(gè)像素),我們知道這條光線與大氣層上邊緣相交的位置。我們此時(shí)需要解決的問題是找出有多少光線在沿著觀察者的方向上傳播。正如我們?cè)谙聢D中看到的那樣,我們的相機(jī)或觀察者不太可能直視太陽(yáng)(那樣會(huì)傷害你的眼睛)。
Figure 7: single scattering is responsible for the sky color. A viewer is rarely directly looking at the sun (which is dangerous). However when we are looking away from the sun the atmosphere has a color which is the result of blue light from the sunlight being scattered in the direction of the observer's eyes.
如果你朝天空的方向看,你不應(yīng)該看到任何東西,因?yàn)槟阏诳纯諘绲目臻g(天體之間的空間)。然而,事實(shí)是你會(huì)看到藍(lán)色,這是由來自太陽(yáng)的光進(jìn)入大氣并被觀察方向上的空氣分子偏轉(zhuǎn)引起的。換句話說,沿著觀察方向沒有來自太陽(yáng)的直射光(除非觀察方向直接指向太陽(yáng)),但是來自太陽(yáng)的光被大氣散射,一些光線最終沿著你的眼睛方向行進(jìn)。這種現(xiàn)象稱為單次散射(在體積渲染內(nèi)容中對(duì)此進(jìn)行了解釋)。
Figure 8: to compute the sky color we first trace a ray from Pc to Pa and then integrate the amount of light coming from the sun (with direction L) that is reflected back along that ray (V).
到目前為止我們知道什么?我們知道,為了渲染幀中一個(gè)像素對(duì)應(yīng)的天空顏色,我們將首先從點(diǎn)Pc(相機(jī)位置)向感興趣的方向上投射觀察光線(V)。我們將計(jì)算此光線與大氣相交的點(diǎn)Pa。最后,我們需要計(jì)算由于單次散射而沿著該光線傳播的光量。該值可以使用我們?cè)隗w積渲染內(nèi)容中研究的體積渲染方程來計(jì)算:
其中T是點(diǎn)Pc和X(沿觀察方向的樣本位置)之間的透射率。L是體積中位置X處的光量。它所說的是,在Pc到達(dá)觀察者的光總量等于沿著觀察方向V散射的所有太陽(yáng)光。該量可以通過將沿V的各個(gè)位置(X)的光相加來獲得,這種技術(shù)稱為數(shù)值積分。我們沿著光線采集的樣本越多,結(jié)果越好,但計(jì)算所需的時(shí)間越長(zhǎng)。等式中的透射率項(xiàng)(T)解釋了在每個(gè)樣本位置(X)處沿觀察者方向V散射的光從X行進(jìn)到Pc時(shí)也會(huì)衰減。
回想一下體積渲染的內(nèi)容,當(dāng)光線從體積中的一個(gè)點(diǎn)移動(dòng)到另一個(gè)點(diǎn)時(shí)因吸收和散射,光線會(huì)衰減。我們稱Pb點(diǎn)的光量為L(zhǎng)b,從Pb到達(dá)Pa點(diǎn)的光量為L(zhǎng)a。存在參與介質(zhì)的情況下,La(從Pb接收的光)將低于Lb。透射率表示La與Lb之比,因此T在0到1的范圍內(nèi)。透射率的方程看起來像這樣:
簡(jiǎn)單來說,這個(gè)等式意味著我們需要測(cè)量沿著路徑光線Pa-Pb在不同樣本位置處的大氣的衰減βe,將這些值加起來,將它們乘以長(zhǎng)度段ds(即距離Pa-Pb除以使用的樣本數(shù)量) ,取該值的負(fù)值并將其提供給指數(shù)函數(shù)。
Figure 9: as light (Lb) travels from Pb to Pa, it gets attenuated because of out-scattering and absorption. The result is La. Transmittance is the amount of light received at Pa from Pb, after it was attenuated while traveling through the atmosphere (that is T=La/Lb).
回到我們所說的關(guān)于瑞利散射的內(nèi)容,你會(huì)記得βs(我們將以此計(jì)算βe)可以用海平面上的散射系數(shù)來計(jì)算,該散射系數(shù)由高度h與大氣標(biāo)高(H)比值的指數(shù)函數(shù)來計(jì)算。
對(duì)于瑞利散射,可以忽略吸收,散射系數(shù)我們可以寫作:
你可以將βe(0)移出積分(因?yàn)樗浅?shù)),透射率方程重新寫為:
指數(shù)函數(shù)內(nèi)的和可以看作Pa和Pb之間的平均密度值,并且方程本身在文獻(xiàn)中通常稱為點(diǎn)Pa-Pb之間的大氣的光學(xué)深度。
1.6 將陽(yáng)光加起來
最后,我們將使用前一段中介紹的渲染方程來計(jì)算天空顏色,讓我們?cè)賹懸槐椋?/p>
我們已經(jīng)解釋了如何計(jì)算透射率,現(xiàn)在讓我們看看Lsun(X)這個(gè)量,并解釋如何評(píng)估它的值。Lsun(X)對(duì)應(yīng)于在樣本位置X處沿觀察方向散射的太陽(yáng)光量。為了評(píng)估它,首先我們需要計(jì)算到達(dá)X的光量,直接取陽(yáng)光強(qiáng)度是不夠的,實(shí)際上,如果光線在Ps點(diǎn)進(jìn)入大氣層,它也會(huì)在行進(jìn)到X過程中衰減。因此,我們需要使用與我們用于計(jì)算沿著從Pa到Pc的觀察方向傳播的光的衰減的方程相似的方程來計(jì)算這種衰減(等式1):
Equation 1
從技術(shù)上講,對(duì)于沿著觀察射線的每個(gè)采樣位置X,我們將需要在太陽(yáng)光方向(L)上投射光線并找到該光線與大氣相交的位置(Ps)。然后,我們將使用與觀察射線相同的數(shù)值積分技術(shù)來評(píng)估等式1中的透射率(或光學(xué)深度)項(xiàng)。將光線切割成段,并評(píng)估每個(gè)光段中心的大氣密度。構(gòu)建計(jì)算天空顏色的算法的最后一個(gè)要素是根據(jù)光線方向本身和視線方向來計(jì)算在觀察方向上散射的光量。這是相函數(shù)的作用,瑞利散射和米氏散射有各自的相函數(shù),我們?cè)谥疤岬竭^它們。如果你需要了解相函數(shù),請(qǐng)閱讀體積渲染相關(guān)內(nèi)容。簡(jiǎn)而言之,相函數(shù)是描述來自方向L的光在方向V上散射多少的函數(shù)。米氏相函數(shù)包含一個(gè)額外項(xiàng)g,稱為平均余弦(可能還有其他名稱),它定義光是否主要沿前向(L)或后向(-L)散射。對(duì)于前向散射,g在[0:1]范圍內(nèi),而后向散射g在[-1:0]范圍內(nèi)。當(dāng)g等于零時(shí),光在所有方向上均勻散射,我們說散射是各向同性的。對(duì)于米氏散射,我們將g設(shè)置為0.76。
最后,我們需要考慮這樣的事實(shí),例如,瑞利散射的藍(lán)光主要沿著視線方向散射。為了反映這一點(diǎn),我們將前一個(gè)方程的結(jié)果乘以散射系數(shù)(βs),這給出了方程的光量部分的完整方程。但是回想一下βs隨高度而變化(它的值是高度的函數(shù)),其中h是X相對(duì)于地面的高度(更精確地說是海平面):
對(duì)于地球大氣而言,太陽(yáng)是天空中唯一的光源,但是,為了寫出前一個(gè)方程的通用形式,我們應(yīng)該考慮光可能來自多個(gè)方向的事實(shí)。在科研論文中,你通常會(huì)看到這個(gè)等式被寫為4π的積分,它描述了傳入方向的范圍。這個(gè)更通用的方程也可以考慮了地面反射的陽(yáng)光(多次散射),我們將在本章中忽略這些多次散射的陽(yáng)光。
1.7 計(jì)算天空顏色
把所有的元素拼接在一起我們得到以下方程(方程2和方程3):
Equation 2
Equation 3
將方程3代入方程2得到以下方程:
相函數(shù)的結(jié)果以及陽(yáng)光強(qiáng)度是恒定的,我們可以將這兩項(xiàng)移到積分外:
Equation 4
這是用于渲染特定視角和光照方向的天空顏色的最終方程。因此,它并不復(fù)雜,但對(duì)它的計(jì)算要求更高,因?yàn)槲覀冇?jì)算積分并對(duì)指數(shù)函數(shù)進(jìn)行多次調(diào)用(通過透射率項(xiàng))。另外,你需要記住它們的天空顏色實(shí)際上是瑞利和米氏散射的結(jié)果。因此,對(duì)于每種散射類型,我們需要計(jì)算兩次這個(gè)方程:
在微積分中,兩個(gè)底數(shù)相同的指數(shù)函數(shù)的乘積可用法則計(jì)算,即底數(shù)不變指數(shù)相加。
我們可以利用這個(gè)屬性(我們計(jì)算一個(gè)指數(shù)而不是兩個(gè))并重新編寫方程4中兩個(gè)透射項(xiàng)的乘法:
Equation 5
2、大氣散射的GPU編碼實(shí)現(xiàn)
在第一部分中已經(jīng)介紹了相應(yīng)的理論基礎(chǔ),在這部分我們將在GPU中實(shí)現(xiàn)對(duì)天空顏色的模擬。由于原文中給出的代碼是在CPU中實(shí)現(xiàn)的,輸出最終的圖片需要一定時(shí)間且不方便調(diào)試預(yù)覽,因此我們利用ShaderToy在GPU中實(shí)現(xiàn),方便修改參數(shù)并實(shí)時(shí)預(yù)覽最終模擬的效果,最終效果如下視頻所示,可以看到隨著太陽(yáng)接近地平線,靠近地平線位置的天空呈現(xiàn)紅色和橙色,另外也可在ShaderToy中看到該實(shí)現(xiàn)
(https://www.shadertoy.com/view/3sSfDz):
Figure 9
下面開始介紹實(shí)現(xiàn)部分,首先是坐標(biāo)系的建立,想象一下中午你東西向躺在草坪上,太陽(yáng)在天空正上方,你戴著墨鏡直視太陽(yáng),以視線直視方向?yàn)閥軸正方向,雙臂展開從左手到右手的方向?yàn)閤軸正方向,從你的腳底到頭頂?shù)姆较驗(yàn)閦軸正方向,坐標(biāo)軸的原點(diǎn)在地心,以此建立一個(gè)左手坐標(biāo)系。在此坐標(biāo)系下平躺著朝著正上方用魚眼相機(jī)每隔一定時(shí)間拍攝一次照片,至太陽(yáng)落山為止,最終將圖像序列按創(chuàng)建時(shí)間順序壓縮成視頻,便得到和如上視頻中類似的效果。為了模擬魚眼效果,需要將單位正方形內(nèi)的點(diǎn)集映射到單位半球面(不是嚴(yán)格的半球面,有一部分點(diǎn)在半球面以下,關(guān)于平面點(diǎn)集到半球面點(diǎn)集的映射,可參考《Ray Tracing from the Ground Up》中有關(guān)內(nèi)容)上,然后從相機(jī)位置處向半球面上的這些點(diǎn)發(fā)射射線計(jì)算每個(gè)點(diǎn)上最終的顏色值。
在ShaderToy中,屏幕從左到右為x正向,從下到上為y正向,uv的x和y分量取值范圍為「0,1」,但屏幕的長(zhǎng)寬不同,屏幕長(zhǎng)度大于寬度,這意味著同一把尺子分別與x和y軸平行時(shí)投影得到的度量不同,x值會(huì)更大些,為了消除這種不一致,需要將uv值的y分量乘以屏幕的長(zhǎng)寬比,然后利用球面坐標(biāo)系的角度和坐標(biāo)的轉(zhuǎn)換公式得到單位正方形內(nèi)的點(diǎn)對(duì)應(yīng)的單位半球面上的點(diǎn),viewScale是為了對(duì)面畫整體進(jìn)行縮放,類似于FOV的作用。
vec2 uv =(2.*fragCoord/iResolution.xy1.)*vec2(iResolution.x/iResolution.y,1.);
float viewScale = 1.;
vec2 p = uv*viewScale;
注意屏幕的xy平面相當(dāng)于上面建立的坐標(biāo)系的xz平面,因此我們可以做如下映射:
//單位正方形內(nèi)的點(diǎn)映射到半球面上
float z2 = p.x*p.x+p.y*p.y;
float phi = atan(p.y,p.x);
float theta = acos(1.-z2);
vec3 dir = vec3(sin(theta)*cos(phi),
cos(theta),
sin(theta)*sin(phi));
ray r = ray(vec3(0.,earthRadius+1.,0.),dir);
color = getIncidentLight(r);
fragColor = vec4(color,1.);
我們將相機(jī)位置放置在(0.,earthRadius+1.0,0.)處,將屏幕坐標(biāo)中單位正方形內(nèi)的點(diǎn)映射到新建立的坐標(biāo)系中單位半球面上的點(diǎn),然后從相機(jī)位置處向半球面上各個(gè)已映射的點(diǎn)發(fā)射射線。由于模擬的是正午到日落的動(dòng)態(tài)效果,需要更新太陽(yáng)的位置,假設(shè)太陽(yáng)從正午到日落沿著我們建立的坐標(biāo)軸的x軸旋轉(zhuǎn)了90度,則可以對(duì)太陽(yáng)光的方向做如下更新:
//sun position
float rotSpeedFactor = 3.;
mat3 sunRot = rotate_around_x(-abs(sin(u_time/rotSpeedFactor))*90.);
sunDir *= sunRot;
沿x軸旋轉(zhuǎn)的變換矩陣可由如下輔助函數(shù)得到:
//繞x軸的旋轉(zhuǎn)矩陣
mat3 rotate_around_x(const in float degrees)
{
float angle = radians(degrees);
float _sin = sin(angle);
float _cos = cos(angle);
return mat3(1.,0.,0.,
0.,_cos,-_sin,
0.,_sin,_cos);
}
接著我們定義一些宏和常量:
#define PI 3.14159265359
#define USE_HENYEY 1
#define u_res iResolution
#define u_time iTime
vec3 sunDir = vec3(0.,1.,0.);
float sunPower = 20.;
const float earthRadius = 6360e3;
const float atmosphereRadius = 6420e3;
const int numSamples = 16;
const int numSamplesLight = 8;//光線與大氣層頂端交點(diǎn)到采樣點(diǎn)的采樣數(shù)量
const float hR = 7994.;//rayleigh
const float hM = 1200.;//mie
const vec3 betaR = vec3(5.5e-6,13.0e-6,22.4e-6);//rayleigh
const vec3 betaM = vec3(21e-6);//mie
然后定義射線和球的struct以及射線與球相交檢測(cè)以及計(jì)算相交點(diǎn)的輔助函數(shù):
struct ray
{
vec3 origin;
vec3 direction;
};
struct sphere
{
vec3 center;
float radius;
};
//表示大氣層的球
const sphere atmosphere = sphere(vec3(0.,0.,0.),atmosphereRadius);
//計(jì)算射線與球是否相交以及交點(diǎn)
bool raySphereIntersect(const in ray r,const in sphere s,inout float t0,inout float t1)
{
vec3 oc = r.origin-s.center;
float a = dot(r.direction,r.direction);
float b = dot(oc,r.direction);
float c = dot(oc,oc)-s.radius*s.radius;
float discriminant = b*b-(a*c);
if(discriminant>0.0)
{
float tmp = sqrt(discriminant);
t0 = -b-tmp;
t1 = -b+tmp;
return true;
}
return false;
}
另外瑞利和米氏以及schlick相函數(shù)的定義如下:
//----------------phase function----------------
float rayleighPhaseFunc(float mu)
{ return 3.*(1.+mu*mu)/(16.*PI);
}
const float g = 0.76;
float henyeyGreensteinPhaseFunc(float mu)
{
return (1.-g*g)/((4.*PI)*pow(1.+g*g-2.*g*mu,1.5));
}
const float k = 1.55*g-0.55*(g*g*g);
float schlickPhaseFunc(float mu)
{
return (1.-k*k)/(4.*PI*(1.+k*mu)*(1.+k*mu));
}
//----------------phase function----------------
相函數(shù)定義為粒子在各個(gè)方向上的實(shí)際散射能,與粒子散射為各向同性時(shí)該方向的散射能之比,輸出是一個(gè)無量綱的值。可以通過desmos上的henyeyGreensteinPhaseFunction的圖像來配合理解。
由于理論中提到最終的顏色值是由積分公式計(jì)算得到的,積分區(qū)間是一個(gè)連續(xù)的區(qū)間,因此只能通過離散采樣的方式計(jì)算累加和得到近似結(jié)果。
//計(jì)算光學(xué)深度
bool getSunLight(const in ray r,inout float opticalDepthR,inout float opticalDepthM)
{
float t0,t1;
raySphereIntersect(r,atmosphere,t0,t1);
float marchPos = 0.;
float marchStep = t1/float(numSamplesLIght);
for(int i = 0;i<numSamplesLIght;i++)
{
//相鄰兩個(gè)采樣點(diǎn)的中點(diǎn)
vec3 s =r.origin+r.direction*(marchPos+0.5*marchStep);
float height = length(s)-earthRadius;
if(height<0.)
return false;
opticalDepthR += exp(-height/hR)*marchStep;
opticalDepthM += exp(-height/hM)*marchStep;
marchPos += marchStep;
}
return true;
}
vec3 getIncidentLight(const in ray r)
{
float t0,t1;
if(!raySphereIntersect(r,atmosphere,t0,t1))
{
return vec3(0.);
}
float marchStep = t1/float(numSamples);
float mu = dot(r.direction,sunDir);
float phaseR = rayleighPhaseFunc(mu);
float phaseM =
#if USE_HENYEY
henyeyGreensteinPhaseFunc(mu);
#else
schlickPhaseFunc(mu);
#endif
float opticalDepthR = 0.;
float opticalDepthM = 0.;
vec3 sumR = vec3(0.);
vec3 sumM = vec3(0.);
float marchPos = 0.;
for(int i=0;i<numSamples;i++)
{
vec3 s = r.origin+r.direction*(marchPos+0.5*marchStep);
float height = length(s)-earthRadius;
//計(jì)算光學(xué)深度累加和
float hr = exp(-height/hR)*marchStep;
float hm = exp(-height/hM)*marchStep;
opticalDepthR += hr;
opticalDepthM += hm;
ray lightRay = ray(s,sunDir);
float opticalDepthLightR = 0.;
float opticalDepthLightM = 0.;
bool bOverGround = getSunLight(lightRay,opticalDepthLightR,opticalDepthLightM);
if(bOverGround)
{
vec3 t = betaR*(opticalDepthR+opticalDepthLightR)+
betaM*1.1*(opticalDepthM+opticalDepthLightM);
vec3 attenuation = exp(-t);
sumR += hr*attenuation;
sumM += hm*attenuation;
}
marchPos += marchStep;
}
return sunPower*(sumR*phaseR*betaR+sumM*phaseM*betaM);
}
通過調(diào)整瑞利散射系數(shù)或米氏散射系數(shù),可以得到一些alien planet atmosphere的效果,如下所示:
此外,如果從相機(jī)位置處向成像平面發(fā)射射線計(jì)算著色,可得到如下渲染效果,比較接近unity中默認(rèn)場(chǎng)景的天空顏色:
大氣渲染相關(guān)的技術(shù)點(diǎn)很多,本文僅實(shí)現(xiàn)了單次散射,對(duì)于多次散射、相函數(shù)推導(dǎo)、優(yōu)化等相關(guān)主題未有涉及,在實(shí)時(shí)渲染中還有其他簡(jiǎn)化模型以及各種trick來渲染天空。
以上就是關(guān)于t1天到賬的pos機(jī),游戲中迷人天空的顏色是如何制作出來的的知識(shí),后面我們會(huì)繼續(xù)為大家整理關(guān)于t1天到賬的pos機(jī)的知識(shí),希望能夠幫助到大家!
