談?wù)勛约旱睦斫獍?/p>
第一次聽說HDR是在我的賓得單反相機(jī)上,有個(gè)HDR的拍攝模式,叫做高動(dòng)態(tài)范圍拍攝,其原理是拍攝一張過曝的圖片,拍攝一張曝光不足的圖片,再拍攝一張正常圖片,相機(jī)只需進(jìn)行一次快門釋放,但這個(gè)功能可以拍攝三張并且自動(dòng)合并,其作用是為了亮部區(qū)域和暗部區(qū)域都能有很豐富的細(xì)節(jié)。
后來從事三維影視相關(guān)的工作,HDR大多用來制作環(huán)境球貼圖,在 PBR 的渲染管線中加入了 IBL(Image Based Lighting)使得渲染結(jié)果更加真實(shí),為離線渲染提供了非常真實(shí)的光線。
隨著游戲業(yè)的畫面水準(zhǔn)開始向電影水準(zhǔn)發(fā)展,越來越多的游戲使用HDR,ToneMapping,ExposureAdjustment等等,我們必須好好理解它并把游戲想電影的畫質(zhì)去推進(jìn)。
HDR的存在能存儲超越圖像存儲介質(zhì)的圖片亮度和細(xì)節(jié),顯示器能夠顯示R、G、B分量在[0,255]之間的像素值,而256個(gè)不同的亮度級別顯然不能表示自然界中光線的亮度情況,HDR再有限的亮度范圍內(nèi)顯示更寬廣的亮度范圍
ExposureAdjustment與相機(jī)的曝光類似,不過引擎里應(yīng)該是計(jì)算render target的平均亮度,然后矯正
ToneMapping是把場景中范圍巨大的亮度值放到范圍有限的存儲空間中來,用ps來表達(dá)就像添加了一個(gè)對比度效果,降低亮度,提升暗部,這個(gè)效果的話就因人而異了。
Bloom可以模擬出HDR的效果,但是原理上和HDR相差甚遠(yuǎn)。Bloom僅僅是能夠?qū)⒘恋牡胤礁痢2贿^效果實(shí)現(xiàn)起來簡單,性能消耗也小,效果也可以接收,對于移動(dòng)平臺很友好。
為了搞懂HDR和Bloom的區(qū)別,我轉(zhuǎn)載了下面這段,感謝原作者:[lupeng0330]
【要比較兩者的異同,得先搞清楚HDR特效是什么;HDR,本身是High-Dynamic Range(高動(dòng)態(tài)范圍)的縮寫,這本來是一個(gè)CG概念。HDR的含義,簡單說,就是超越普通的光照的顏色和強(qiáng)度的光照。計(jì)算機(jī)在表示圖象的時(shí)候是用8bit(256)級或16bit(65536)級來區(qū)分圖象的亮度的,但這區(qū)區(qū)幾百或幾萬無法再現(xiàn)真實(shí)自然的光照情況。因此普通情況下,無法同時(shí)顯示亮部和暗部的所有細(xì)節(jié)。
想要實(shí)現(xiàn)HDR特效,首先,游戲開發(fā)者要在游戲開發(fā)過程中,利用開發(fā)工具(就是游戲引擎)將實(shí)際場景用HDRI記錄下來,當(dāng)然開發(fā)技術(shù)強(qiáng)的開發(fā)組會直接用小開發(fā)工具(比如3D MAX的某些特效插件)創(chuàng)造HDRI圖像;其次,我們的顯卡必須支持顯示HDR特效,nVIDIA的顯卡必須是GeForce 6系列或更高,ATI顯卡至少是Radeon 9550或以上。
那么HDR與bloom效果的差別到底在什么地方呢?
第一,HDR效果就是超亮的光照與超暗的黑暗的某種結(jié)合,這個(gè)效果是光照產(chǎn)生的,強(qiáng)度、顏色等方面是游戲程序可動(dòng)態(tài)控制的,是一種即時(shí)動(dòng)態(tài)光影;bloom效果則是物體本身發(fā)出的光照,僅僅是將光照范圍調(diào)高到過飽和,是游戲程序無法動(dòng)態(tài)控制的,是一種全屏泛光。
第二,bloom效果無需HDR就可以實(shí)現(xiàn),但是bloom效果是很受限的,它只支持8位RGBA,而HDR最高支持到32位RGBA。
第三,bloom效果的實(shí)現(xiàn)很簡單,比如《半條命2》的MOD就是一個(gè)很小的很簡單的MOD,而且bloom效果不受顯卡的規(guī)格的限制,你甚至可以在TNT顯卡上實(shí)現(xiàn)bloom效果(當(dāng)然效果很差)!而HDR,必須是6XXX以上的顯卡才能夠?qū)崿F(xiàn),這里的HDR是指nVIDIA的HDR。這時(shí)有必要談nVIDIA和ATI的顯卡所實(shí)現(xiàn)的HDR,兩者還是有區(qū)別的,具體區(qū)別就很專業(yè)了,總之從真實(shí)性表現(xiàn)來看,nVIDIA的顯卡實(shí)現(xiàn)的HDR更好一些。HDR是nVIDIA提出的概念,從技術(shù)上來講,ATI當(dāng)然無法嚴(yán)格克隆nVIDIA的技術(shù),所以ATI的HDR是另一種途徑實(shí)現(xiàn)的盡可能接近的HDR,不能算“真”HDR,據(jù)傳ATI的R520能夠真正實(shí)現(xiàn)FP16 HDR?!?/p>


接下來要實(shí)現(xiàn)Bloom
第一步: 先獲取屏幕圖像,然后對每個(gè)像素進(jìn)行亮度檢測,若大于某個(gè)閥值即保留原始顏色值,否則置為黑色;
第二步:對上一步獲取的圖像,做一個(gè)模糊,通常使用高斯模糊。
第三步:將模糊后的圖片和原圖片做一個(gè)加權(quán)和。

核心代碼:
//申請兩塊RT,并且分辨率按照downSameple降低
RenderTexture temp1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
RenderTexture temp2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
//直接將場景圖拷貝到低分辨率的RT上達(dá)到降分辨率的效果
Graphics.Blit(source, temp1);
//根據(jù)閾值提取高亮部分,使用pass0進(jìn)行高亮提取
_Material.SetVector("_colorThreshold", colorThreshold);
Graphics.Blit(temp1, temp2, _Material, 0);
//高斯模糊,兩次模糊,橫向縱向,使用pass1進(jìn)行高斯模糊
_Material.SetVector("_offsets", new Vector4(0, samplerScale, 0, 0));
Graphics.Blit(temp2, temp1, _Material, 1);
_Material.SetVector("_offsets", new Vector4(samplerScale, 0, 0, 0));
Graphics.Blit(temp1, temp2, _Material, 1);
//Bloom,將模糊后的圖作為Material的Blur圖參數(shù)
_Material.SetTexture("_BlurTex", temp2);
_Material.SetVector("_bloomColor", bloomColor);
_Material.SetFloat("_bloomFactor", bloomFactor);
//使用pass2進(jìn)行景深效果計(jì)算,清晰場景圖直接從source輸入到shader的_MainTex中
Graphics.Blit(source, destination, _Material, 2);
//釋放申請的RT
RenderTexture.ReleaseTemporary(temp1);
RenderTexture.ReleaseTemporary(temp2);
Shader:
pass1
//僅當(dāng)color大于設(shè)置的閾值的時(shí)候才輸出
return saturate(color - _colorThreshold);
pass2
//模糊
o.uv01 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1);
o.uv23 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 2.0;
o.uv45 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 3.0;
fixed4 color = fixed4(0,0,0,0);
color += 0.40 * tex2D(_MainTex, i.uv);
color += 0.15 * tex2D(_MainTex, i.uv01.xy);
color += 0.15 * tex2D(_MainTex, i.uv01.zw);
color += 0.10 * tex2D(_MainTex, i.uv23.xy);
color += 0.10 * tex2D(_MainTex, i.uv23.zw);
color += 0.05 * tex2D(_MainTex, i.uv45.xy);
color += 0.05 * tex2D(_MainTex, i.uv45.zw);
return color;
pass3
//輸出= 原始圖像,疊加bloom權(quán)值*bloom顏色*泛光顏色
fixed4 final = _MainTex + _bloomFactor * blur * _bloomColor;

