ETH官方钱包

切換
舊版
前往
大廳
主題

Tone mapping之camera模擬

Lumi | 2015-11-07 12:29:09 | 巴幣 0 | 人氣 359


▲模擬被燈泡照明的米卡莎
光圈 f/1.4, 快門 0.1s, ISO400, 光源色溫2700K, 730流明

這回的目標是在tonemapping中模擬相機一部分特性,這次的參考資料是來自寒霜引擎。在實作之前,我們首先得搞清楚pixel內到底儲存的是甚麼東西。

Render target中每個pixel代表底片中的一小塊區域,寒霜引擎在pixel中儲存的光線單位是使用illuminance而不是irradiance。illuminance是光度單位,每種光度單位都可以對應到一個輻射量單位,光度單位之間的關係可以直接套用輻射量單位之間的關係,先前已有說明因此不再詳述。

Radiant energy J (焦耳)
Luminous energy
lm·s
Radiant flux
J/s or W (瓦特)
Luminous flux
lm (流明 Lumen)
Radiant intensity
W/sr
Luminous intensity
lm/sr or cd (燭光 Candela)
Irradiance
W/m2
Illuminance
lm/m2 or lx (勒克斯 Lux)
Radiance
W/(m2·sr) Luminance
lm/(m2·sr)
▲輻射量單位與光度單位對應表
光度單位大都以我的名字開頭 (毆飛

寒霜選擇illuminance有數個理由,首先現實中的光源通常都使用光度單位,美術也使用光度單位。若render target採用irradiance,引擎多了一個轉換功夫,美術除了為每個光源提供流明之外,還必須提供發光效率,增加美術的負擔。

發光效率為100%時,luminous flux與radiant flux的比值為683,此數值可被引擎用來作光度與輻射量單位間的換算。因為人眼對不同波長有不同的敏感度,所以即使兩種光源消耗相同能量,兩者發出的不同光譜有可能造成發光效率的不同。由下表可知不同光源之間效率相差數倍或數百倍,無法為了省功夫而全部採用同一個預設值。

燭光 0.04%
白熾燈 2%~5%
LED燈 0.66~22%
螢光燈 8%~15%
太陽 13.6%
▲常見光源之發光效率,取自wiki

要得到發光效率除了用光譜計算,就只能靠商品上的標示了。雖然偶爾還是能在購物網站上找到有標示的商品,不過還不如引擎內全面改用光度單位來的省事。


▲某購物網站的商品頁面只教你怎麼辨識,但不提供數據... (怒

說到購物網站,燈泡的顏色通常只會標示色溫,而不是RGB。色溫即黑體輻射體處於某溫度時所發出的顏色,例如色溫2700K代表黑體輻射體的溫度2700K時所發出的顏色。為了得知燈泡的顏色必須實作色溫轉換RGB,我的實作參考了這個網站。簡單來說(?)就是利用普朗克黑體輻射定律,從溫度求出黑體輻射體所發出的光譜,再從光譜求出人眼所看到的顏色。

光線的發出和儲存都搞定了,接著該搞定曝光。這部分簡單許多,計算可以直接套用公式,公式與其推導過程可見wiki或寒霜文件,寒霜使用的方法是Saturation-based speed。光線經過曝光計算後,大部分會被壓縮到0~1區間。在這裡應該再要加上一道查表步驟,模擬底片的特性,不過我還沒找到作法,只能先切掉大於1的部分,當作過度曝光。最後一步是做gamma校正(RGB轉sRGB),因為gamma曲線其實不是很平滑,寒霜推薦轉換sRGB的演算法採用精確版本,而非以往的近似版本,接近黑色的顏色才會比較準確。

因為沒有準備光度單位的environment map,因此測試用場景只在角落放了四個點光源:

▲光圈 f/1.4, 快門 0.1s, ISO400, 色溫5000K, 1500流明


▲加上color grading以模擬底片特性

該做的還有很多,找到更好的底片特性模擬法、用ray-tracing驗證光線演算法是否正確、生出IBL用的cube map,如果Vulkan出的話還要開始移植。說到Vulkan,Nvidia似乎差不多準備好了,還不出嗎?

創作回應

更多創作