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一文中给出简要且效果不错的公式
关键代码如下
- 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效果。
高斯模糊的滤波器是一种低通滤波器
就是去当前像素和周围的像素按一定权重混合,产生一定模糊效果
权重分布如下,离当前像素越远,权重越低
高斯正态分布曲线
二维公式
可以通过这个公式直接算出权重
- 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滤波器
有现成的就不算了,算这个也消耗一些性能
我们直接用这个权重
关键代码如下
- 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,也不影响亮度。
- float lum = Luminance(c);
- c = mc22mc + c * (lum+0.1) * _Lum;
- return float4(c,1);
最终与HDR结合再一起就是上图例子的最终效果
最后一道工序就是放入相机中,我们建立一个c#并负责传值
代码如下:
- 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效果(高动态范围图像和泛光)相关推荐
- HDR和bloom效果的区别和关系
什么是HDR? 谈论游戏画面时常说的HDR到底是什么呢?HDR,本身是High-Dynamic Range(高动态范围)的缩写,这本来是一个CG概念.HDR的含义,简单说,就是超越普通的 ...
- 高动态范围图像HDR
HDR(High Dynamic Range,高动态范围),由于目前无论是相机还是显示器,对图像亮度范围都限定在0~255之间,即256个亮度级别,但在自然界中,刺眼的阳光和微弱的星光,可能有成千上万 ...
- 局部边缘保持滤波(LEP)高动态范围图像HDR压缩 python实现
(9条消息) 局部边(9条消息) 局部边缘保持滤波(LEP)高动态范围图像HDR压缩 matlab程序(一)_ 本文程序根据论文"Gu B, Li W, Zhu M, et al. Loca ...
- Learn OpenGL 笔记6.8 Bloom(高动态范围)
由于monitor监视器的强度范围有限,明亮的光源和明亮的区域通常难以传达给观看者. 区分显示器上明亮光源的一种方法是让它们发光: 然后光线在光源周围流淌. 这有效地为观看者提供了这些光源或明亮区域非 ...
- HDR Efex Pro 2 高动态范围滤镜
HDR Efex Pro 2 采用独特的色调映射算法,可协助专业和业余摄影师创造出无比自然或极具艺术效果的 HDR 照片. HDR Efex Pro 2 提供了 28 种预设,包括:实际 Realis ...
- 高动态范围图像是什么
HDR(High-Dynamic Range,译为高动态范围图像)是一个被大量抛出的术语,似乎从来没有真正得到解释.你看在你的手机拍摄 HDR 照片,电视显示 HDR 视频,这究竟意味着什么?它代表高 ...
- UnityShader入门精要-屏幕后处理效果 亮度饱和度对比度、边缘检测、高斯模糊、bloom效果、运动模糊
(从这里开始可能会记录的更简略一些,时间紧张想迅速读完这本书的主要内容,可能有的部分不会自己上手做) 屏幕后处理通常指渲染完整个场景得到屏幕图像后,再对图像进行操作,抓取屏幕可以使用OnRenderI ...
- 高动态范围图像-单图
高动态范围图像-单图 左侧是原图,右侧是处理后的图
- Unity3d 实现落叶飘效果
Unity3d 实现落叶飘效果 一. 演示效果: 1.gif图演示 2.视频演示 二.快速开始 1.下载插件 2.使用教程 三.代码概述: 1.LeavesLife.cs 2.LeavesSpwan. ...
最新文章
- H5面试题---介绍js的基本数据类型
- 苹果员工“神操作”:自建网站揭露公司性骚扰和歧视事件
- 请人安装linux系统,我想安装linux操作系统,请指导一下
- 一个可视化的retrospective网站
- Spring MVC 3 深入总结
- 讲道理,我觉得TensorFlow太逊了
- radio按钮样式美化和checkbox按钮样式美化
- 国内计算机期刊SCI收录
- 封装设计 SLC、MLC和TLC
- 大数据课程30天掌握 spark内存计算(python )-徐培成-专题视频课程
- 盛京剑客系列26:极简估值教程——第二讲历史估值的参考与运用
- CNVD-2020-10487(CVE-2020-1938)tomcat ajp 文件读取漏洞
- 小智机器人型号_小智类人型机器人
- Peewee fn 用法
- word文件打开之后不能编辑是怎么回事
- Layui写后台登录页面 蓝奏云 下载
- Cisco路由器入侵
- 使用PS快速抠图:(磁锁套抠图,快速工具,)
- ROHM | 面向高端ADAS开发出业界超稳定运行的DC-DC转换器IC“BD9S402MUF-C”
- 抛物线中四边形面积最大值_函数动点与四边形面积最大值
热门文章
- android 百度悬浮搜索框,百度的搜索框效果如何实现的???
- arm开发板上电设置静态ip_与X86/Arm三分天下,RISCV还需几步?
- linux基本知识点学习
- linux 修改dmi信息,如何从linux清除DMI系统事件日志?
- leetcode @38报数-js
- 已禁用对分布式事务管理器(MSDTC)的网络访问。请使用组件服务管理工具启用 DTC 以便在 MSDTC 安全配置中进行网络访问。...
- IDC:以太网交换机市场增长2%
- BZOJ 3160 FFT+Manacher
- nginx 安装禅道
- 05-Windows Server 2012 R2 会话远程桌面-标准部署-RD连接代理高可用性(RemoteApp)