日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Unity3d HDR和Bloom效果(高动态范围图像和泛光)

發布時間:2025/7/25 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity3d HDR和Bloom效果(高动态范围图像和泛光) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章開始先放兩組效果,文章結尾再放兩組效果
本文測試場景資源來自淺墨大神,shader效果為本文效果



HDR

人們有限的視覺系統,只支持16.7百萬的顏色,超出這個范圍的顏色就不能顯示了
bmp或jprg每個像素就是16,24或32位
每個像素都由紅綠藍構成,如果儲存為24位,每個值的范圍就在0,255之間,
只能表現出256:1的差別,unity的shader中是0到1
然而在自然中太陽光下的對比度是50000:1
HDR(High Dynamic Range)使圖像能表現出更大范圍的對比,普通的范圍就叫LDR(Low Dynamic Range)

你在照相的時候能控制曝光時間從而控制亮度。
HDR效果就是可控的曝光,

色調映射 tone-mapping

傳統的顯示設備不能完全的顯示出HDR,所以我們用tone-mapping技術。
tone-mapping讓圖像從HDR映射為LDR顯示
http://www.ownself.org/blog/2011/tone-mapping.html中的解釋很好
Tone Mapping原是攝影學中的一個術語,因為打印相片所能表現的亮度范圍不足以表現現實世界中的亮度域,而如果簡單的將真實世界的整個亮度域線性壓縮到照片所能表現的亮度域內,則會在明暗兩端同時丟失很多細節,這顯然不是所希望的效果,Tone Mapping就是為了克服這一情況而存在的,既然相片所能呈現的亮度域有限則我們可以根據所拍攝場景內的整體亮度通過光圈與曝光時間的長短來控制一個合適的亮度域,這樣既保證細節不丟失,也可以不使照片失真。人的眼睛也是相同的原理,這就是為什么當我們從一個明亮的環境突然到一個黑暗的環境時,可以從什么都看不見到慢慢可以適應周圍的亮度,所不同的是人眼是通過瞳孔來調節亮度域的。
一個tone-mapping的公式

?



Middlegrey為全屏幕或部分屏幕的中間灰度,可以控值屏幕的亮度
AvgLogLuminance就是全屏幕或部分屏幕的亮度的對數的平均值
?
AvgLogLuminance的公式
Lw是亮度,n是所取亮度數

這個操作能讓L值限制位[0,1)
一些tone-mapping操作用exposure或gamma作為參數控制最終的圖像。
tone-mapping是非線性的,他對暗色保有一定范圍并且對亮色逐步接近動態
這個技術產生吸引人的視覺效果,有著強烈的對比和細節。

HDR Rendering In OpenGL一文中給出簡要且效果不錯的公式
?
關鍵代碼如下

[cpp]?view plain?copy
  • float4?frag(v2f?i)?:COLOR??
  • {??
  • ????float4?c?=?tex2D(_MainTex,?i.uv_MainTex);??
  • ????float?y?=?dot(float4(0.3,0.59,0.11,1),c);??
  • ????float?yd?=?_Exp?*?(_Exp?/?_BM?+?1)?/?(_Exp?+?1);??
  • ????return?c*yd;??
  • }??

  • _Exp,_BM為外部可控變量

    HDR流程如下

    ?



    如果分不清HDR與加亮light,可以看看skybox,加亮light是不會加亮skybox的,HDR使顏色更鮮明,像素更清晰。


    Bloom泛光

    輝光的原因是由于人眼晶狀體的散射
    我們制造bloom的原理是把圖像的亮的部分通過卷積模糊再疊加到原圖像上,就產生了bloom效果。
    高斯模糊的濾波器是一種低通濾波器
    就是去當前像素和周圍的像素按一定權重混合,產生一定模糊效果

    權重分布如下,離當前像素越遠,權重越低


    ?
    高斯正態分布曲線

    ?


    二維公式

    可以通過這個公式直接算出權重
    [cpp]?view plain?copy
  • double?sigma?=?(double)radius?/?3.0;??
  • double?sigma2?=?2.0?*?sigma?*?sigma;??
  • double?sigmap?=?sigma2?*?PI;??
  • ??
  • for(long?n?=?0,?i?=?-?radius;?i?<=radius;?++i)??
  • {??
  • ????long?i2?=?i?*?i;??
  • ????for(long?j?=?-radius;?j?<=?radius;?++j,?++n)??
  • ????????kernel[n]?=?exp(-(double)(i2?+?j?*?j)?/?sigma2)?/?sigmap;??
  • ?}??


  • Kernel即為權重
    Radius為所求像素與當前像素距離(半徑)


    針對這個公式我們可以算出3*3,5*5,7*7等濾波器,出于性能考慮,我們還是使用5*5濾波器


    ?3*3濾波器


    ?5*5濾波器

    有現成的就不算了,算這個也消耗一些性能
    我們直接用這個權重
    關鍵代碼如下
    [cpp]?view plain?copy
  • ????????????float3?mc00?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(2,2)/_inten).rgb;??
  • ????????????float3?mc10?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(1,2)/_inten).rgb;??
  • ????????????float3?mc20?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(0,2)/_inten).rgb;??
  • ????????????float3?mc30?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-1,2)/_inten).rgb;??
  • ????????????float3?mc40?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-2,2)/_inten).rgb;??
  • ??
  • ????????????float3?mc01?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(2,1)/_inten).rgb;??
  • ????????????float3?mc11?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(1,1)/_inten).rgb;??
  • ????????????float3?mc21?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(0,1)/_inten).rgb;??
  • ????????????float3?mc31?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-1,1)/_inten).rgb;??
  • ????????????float3?mc41?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-2,1)/_inten).rgb;??
  • ??
  • ????????????float3?mc02?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(2,0)/_inten).rgb;??
  • ????????????float3?mc12?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(1,0)/_inten).rgb;??
  • ????????????float3?mc22mc?=?tex2D?(_MainTex,?i.uv_MainTex).rgb;??
  • ????????????float3?mc32?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-1,0)/_inten).rgb;??
  • ????????????float3?mc42?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-2,0)/_inten).rgb;??
  • ??????????
  • ????????????float3?mc03?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(2,-1)/_inten).rgb;??
  • ????????????float3?mc13?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(1,-1)/_inten).rgb;??
  • ????????????float3?mc23?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(0,-1)/_inten).rgb;??
  • ????????????float3?mc33?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-1,-1)/_inten).rgb;??
  • ????????????float3?mc43?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-2,-1)/_inten).rgb;??
  • ??
  • ????????????float3?mc04?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(2,-2)/_inten).rgb;??
  • ????????????float3?mc14?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(1,-2)/_inten).rgb;??
  • ????????????float3?mc24?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(0,-2)/_inten).rgb;??
  • ????????????float3?mc34?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-1,-2)/_inten).rgb;??
  • ????????????float3?mc44?=?tex2D?(_MainTex,?i.uv_MainTex-fixed2(-2,-2)/_inten).rgb;??
  • ????????????float3?c=0;??
  • c+=(mc00+mc40+mc04+mc44);//4??
  • c+=4*(mc10+mc30+mc14+mc34+mc01+mc41+mc03+mc43);//16??
  • c+=7*(mc20+mc24+mc02+mc42);//16??
  • c+=16*(mc11+mc13+mc03+mc33);//32??
  • c+=26*(mc21+mc23+mc12+mc32);//64??
  • c+=41*mc22mc;//32??
  • c/=273;??

  • _inten為模糊程度


    覺得冗長麻煩也可用for循環代替。


    然后我們要取其中的亮色部分與原有圖像混合,
    這一部分直接調用unity內部函數Luminance函數求出亮度,把它與模糊的圖像相乘,暗色部分自然消除
    但如果直接相乘就會在暗色的邊緣產生不自然的黑影,就是把暗色也“泛光了”,為此我們不讓Luminance后的值為0,再加上0.1,也不影響亮度。
    [cpp]?view plain?copy
  • float?lum?=?Luminance(c);??
  • c?=?mc22mc?+?c?*?(lum+0.1)?*?_Lum;??
  • return?float4(c,1);??



  • 最終與HDR結合再一起就是上圖例子的最終效果



    最后一道工序就是放入相機中,我們建立一個c#并負責傳值

    代碼如下:


    [csharp]?view plain?copy
  • using?UnityEngine;??
  • using?System.Collections;??
  • [ExecuteInEditMode]??
  • public?class?HDRGlow?:?MonoBehaviour?{??
  • ????#region?Variables??
  • ????public?Shader?curShader;??
  • ????private?Material?curMaterial;??
  • ????public?float?exp?=?0.4f;??
  • ????public?float?bm?=?0.4f;??
  • ????public?int?inten?=?512;??
  • ????public?float?lum?=?1f;??
  • ????#endregion??
  • ?
  • ????#region?Properties??
  • ????Material?material??
  • ????{??
  • ????????get??
  • ????????{??
  • ????????????if?(curMaterial?==?null)??
  • ????????????{??
  • ????????????????curMaterial?=?new?Material(curShader);??
  • ????????????????curMaterial.hideFlags?=?HideFlags.HideAndDontSave;??
  • ????????????}??
  • ????????????return?curMaterial;??
  • ????????}??
  • ????}??
  • ????#endregion??
  • ??
  • ????void?Start()??
  • ????{??
  • ????????if?(!SystemInfo.supportsImageEffects)??
  • ????????{??
  • ????????????enabled?=?false;??
  • ????????????return;??
  • ????????}??
  • ??
  • ????????if?(!curShader?&&?!curShader.isSupported)??
  • ????????{??
  • ????????????enabled?=?false;??
  • ????????}??
  • ????}??
  • ??
  • ????void?OnRenderImage(RenderTexture?sourceTexture,?RenderTexture?destTexture)??
  • ????{??
  • ????????if?(curShader?!=?null)??
  • ????????{??
  • ????????????material.SetFloat("_Exp",?exp);??
  • ????????????material.SetFloat("_BM",?bm);??
  • ????????????material.SetFloat("_Inten",?inten);??
  • ????????????material.SetFloat("_Lum",?lum);??
  • ????????????Graphics.Blit(sourceTexture,?destTexture,?material);??
  • ????????}??
  • ????????else??
  • ????????{??
  • ????????????Graphics.Blit(sourceTexture,?destTexture);??
  • ????????}??
  • ????}??
  • ????void?OnDisable()??
  • ????{??
  • ????????if?(curMaterial)??
  • ????????{??
  • ????????????DestroyImmediate(curMaterial);??
  • ????????}??
  • ????}??
  • }??








  • Unity 的imageEffect有一個叫做BloomAndLensFlares

    與本文的差別是多了色彩平衡和lens flare效果,可以試著再加上去


    ??????????????????????????????????????????????????????? -------? by wolf96 http://blog.csdn.net/wolf96

    總結

    以上是生活随笔為你收集整理的Unity3d HDR和Bloom效果(高动态范围图像和泛光)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。