HDRFilmic Tonemapping Operators
博主在unity5上的渲染结果,第一张图片是母校图书馆 ^ _ ^
但是随着游戏业的画面水准开始向电影水准发展,就需要我们有更好的理解HDR,来进一步把游戏像电影画质推进,这也是近几年的GDC和siggraph上都有一线studio在推HDR相关的技术,比如naughty dog10年的filmic tone mapping,11年crytek在siggraph里面提到的physically based hdr等。
- dynamic range:reinhard的<tone mapping>论文中定义:一个场景中最高亮度与最低亮度的比是dynamic range。
- low dynamic range : 之所以出现这种情况是图像存储介质(打印纸,照片,电脑屏幕等)精度有限造成的,导致在range上没法完全记录一个场景的亮度信息,只能记录有限的一部分,比如游戏里常见的在rgba8上渲染,每个channel大于1的部分就被截取到1了。
- high dynamic range : 准确讲是high dynamic range imaging,是指一种图像技术,它能让图像表示一个比原有技术(之前的LowDynamicRange)更大(greater)的dynamic range
- 这样就可以更加准确和真实的描绘一个场景
oneMapping&ExposureAdjustment
- 自动根据亮度矫正明暗:让我们晚上看东西也能比较清楚,一开灯眼睛要矫正一会回来
- 局部适应性:比较经典的图是:
- 曝光率问题---解决:exposure adjustment。和照相时候曝光原理差不多,白天亮曝光就短一些,晚上曝光长一些,编程时候就是计算render target的平均亮度,然后矫正,这样沙漠的白天和丛林的夜晚都可以在游戏中的rgba8上有一个良好的体现。在hable的论文里,这个属于不同的场景之间的处理问题范畴。
- 压缩的过程中不可避免的涉及到重新分配亮度值,怎么做来得到更好的尽可能不失真的画面这个解决方案就是tone mapping
实际中也有把这个exposure adjustment并到tone mapping中去,其实还是分开比较好,因为这些概念是从摄像技术中来的,曝光就是曝光,tone mapping就是tone mapping。
- zone:存储空间的亮度阶这么一个概念,比如print只有11个zone
- middle grey:中间的亮度
- dynamic range:指场景中最高亮度与最低亮度的比值
- 这是一个最学术派的定义,具体上摄像师一般会追求细节还可以明辨的range
- key:描述整个场景亮度的数值
- dodging and burning:把高亮度的东西亮度降低为dodging,把低亮度的部分加亮为burning
Filmic Tonemapping Operators
The most common questions that I get about my GDC talk have to do with the tonemapping operators. In particular, I’ve always found that when I read through presentations for code snippets that I always miss something. Those 2.2s can be tricky! So this post is a quick reference for various operators that I talked about. Also, I copied and pasted this code from my RenderMonkey scene so there may be typos.
All of these examples use this HDR image of Habib’s killer condo. Also, click any image for the high-res version.
First off, there is good old linear. All it does is read the linear data, do an exposure adjustment, and adjust for the monitor’s gamma of 2.2.
1.
float4 ps_main( float2 texCoord : TEXCOORD0 ) : COLOR
2.
{
3.
float3 texColor = tex2D(Texture0, texCoord );
4.
texColor *= 16;
// Hardcoded Exposure Adjustment
5.
float3 retColor =
pow
(texColor,1/2.2);
6.
return
float4(retColor,1);
7.
}
Pretty simple. It looks like this. Click for high-res.
Don’t forget the pow(1/2.2). If you forget that step, it looks like this:
1.
float4 ps_main( float2 texCoord : TEXCOORD0 ) : COLOR
2.
{
3.
float3 texColor = tex2D(Texture0, texCoord );
4.
texColor *= 16;
// Hardcoded Exposure Adjustment
5.
float3 retColor = texColor;
6.
return
float4(retColor,1);
7.
}
Next up is Reinhard. There are many variations, bu I’ll do the simplest which is 1/(1+x). A common variation is to only do it on luminance. Don’t forget the pow(1/2.2) at the end!
1.
float4 ps_main( float2 texCoord : TEXCOORD0 ) : COLOR
2.
{
3.
float3 texColor = tex2D(Texture0, texCoord );
4.
texColor *= 16;
// Hardcoded Exposure Adjustment
5.
texColor = texColor/(1+texColor);
6.
float3 retColor =
pow
(texColor,1/2.2);
7.
return
float4(retColor,1);
8.
}
Here it is with Haarm-Peter Duiker’s curve. This version is very similar to the Cineon node in Digital Fusion. The texture FilmLut refers tothis TGA file. No pow(1/2.2) necessary.
01.
float4 ps_main( float2 texCoord : TEXCOORD0 ) : COLOR
02.
{
03.
float3 texColor = tex2D(Texture0, texCoord );
04.
texColor *= 16;
// Hardcoded Exposure Adjustment
05.
06.
float3 ld = 0.002;
07.
float
linReference = 0.18;
08.
float
logReference = 444;
09.
float
logGamma = 0.45;
10.
11.
float3 LogColor;
12.
LogColor.rgb = (
log10
(0.4*texColor.rgb/linReference)/ld*logGamma + logReference)/1023.f;
13.
LogColor.rgb = saturate(LogColor.rgb);
14.
15.
float
FilmLutWidth = 256;
16.
float
Padding = .5/FilmLutWidth;
17.
18.
// apply response lookup and color grading for target display
19.
float3 retColor;
20.
retColor.r = tex2D(FilmLut, float2( lerp(Padding,1-Padding,LogColor.r), .5)).r;
21.
retColor.g = tex2D(FilmLut, float2( lerp(Padding,1-Padding,LogColor.g), .5)).r;
22.
retColor.b = tex2D(FilmLut, float2( lerp(Padding,1-Padding,LogColor.b), .5)).r;
23.
24.
return
float4(retColor,1);
25.
}
Next up is the optimized formula by Jim Hejl and Richard Burgess-Dawson. I completely forgot about Richard in the GDC talk, but he shares the credit with Jim. Sorry Richard!! Note that you don’t need the pow(1/2.2) for this one either.
1.
float4 ps_main( float2 texCoord : TEXCOORD0 ) : COLOR
2.
{
3.
float3 texColor = tex2D(Texture0, texCoord );
4.
texColor *= 16;
// Hardcoded Exposure Adjustment
5.
float3 x = max(0,texColor-0.004);
6.
float3 retColor = (x*(6.2*x+.5))/(x*(6.2*x+1.7)+0.06);
7.
return
float4(retColor,1);
8.
}
Finally for the Uncharted 2 operator made by yours-truly. For this image I changed the defaults slightly for A and B.
Edit: Oops, in the previous version, I had the exposure bias outside the tonemapping function. Now it is fixed, where it is inside the tonemapping function.
01.
float
A = 0.15;
02.
float
B = 0.50;
03.
float
C = 0.10;
04.
float
D = 0.20;
05.
float
E = 0.02;
06.
float
F = 0.30;
07.
float
W = 11.2;
08.
09.
float3 Uncharted2Tonemap(float3 x)
10.
{
11.
return
((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
12.
}
13.
14.
float4 ps_main( float2 texCoord : TEXCOORD0 ) : COLOR
15.
{
16.
float3 texColor = tex2D(Texture0, texCoord );
17.
texColor *= 16;
// Hardcoded Exposure Adjustment
18.
19.
float
ExposureBias = 2.0f;
20.
float3 curr = Uncharted2Tonemap(ExposureBias*texColor);
21.
22.
float3 whiteScale = 1.0f/Uncharted2Tonemap(W);
23.
float3 color = curr*whiteScale;
24.
25.
float3 retColor =
pow
(color,1/2.2);
26.
return
float4(retColor,1);
27.
}
Hopefully, that should clear up most of the ambiguity about these operators.
HDRFilmic Tonemapping Operators相关推荐
- Filmic Tonemapping Operators
http://filmicworlds.com/blog/filmic-tonemapping-operators/ 转载于:https://www.cnblogs.com/guochen/p/992 ...
- 图形渲染技术分享:《GTA V 》图形分析摘要
环境渲染 最外层的 cubemap 是每一帧实时生成的,目的是简化后续真实反射的渲染. 这个 cubemap 是一张低精度的 128*128 纹理,每个面 30 左右 drawcall,都是地表天空等 ...
- Tone Mapping(简洁直观的Tonemapping介绍)
转自:https://64.github.io/tonemapping/ What is tone mapping? Most monitors are capable of displaying R ...
- RxJS - Observables, observers 和 operators 简介
RxJS 是响应式编程 (reactive programming) 强大的工具,今天我们将深入介绍 Observables 和 Observers 的内容,以及介绍如何创建自己的操作符 (opera ...
- HDR (automatic exposure control + Tonemapping + Bloom)
<div class="markdown_views"><!-- flowchart 箭头图标 勿删 --><svg xmlns="http ...
- Effective C++ 读书笔记之Part2.Constructors, Destructors, and Assignment Operators
5.Know what functions C++ silently writes and calls. 总结:编译器可以暗自为class创建default构造函数.copy构造函数.copy ass ...
- 一周一论文(翻译)——[VLDB 19] Minimizing Cost by Reducing Scaling Operators in Distributed Stream Processing
Abstract 弹性分布式流处理系统能够动态地适应工作负载的变化.通常,这些系统通过向上或向下扩展来对输入数据的速率或资源利用水平做出反应.目标是优化系统的资源使用,从而降低其运营成本.但是,这种扩 ...
- Python编程基础:第九节 逻辑运算Logical Operators
第九节 逻辑运算Logical Operators 前言 实践 前言 常用的逻辑运算共分为三种:与(and).或(or).非(not).与运算就是同真才真,有假则假:或运算就是有真则真,同假才假:非运 ...
- Blender文档翻译:Operators tutorial(操作教程)
原文:https://wiki.blender.org/index.php/Dev:2.5/Source/Architecture/Operators/Tutorial 逐行解释操作如何工作的.首先解 ...
最新文章
- wpf每隔一小时_包河区徐河排涝站24小时不间断运作 11座区管泵站全面应战保安澜...
- MySQL——数据库的增删改操作
- 使用numpy与matplotlib.pyplot画图
- EF Code First学习笔记:数据库创建(转)
- mesh渲染到ui_在Unity中使用UGUI修改Mesh绘制几何图形
- 用Linux同时编辑两个文档,如何使用Vim编辑多个文件
- 佛山高新区构建大数据产业新生态
- 熟悉 scrollTop ,轻松做5个方面的事情。
- WebStorm配置(2016/11/18更新)
- 桌面图标拖不动怎么办?
- 关于LocalDateTime的全局返回时间带“T“的时间格式处理
- [Unity存档系统]简单介绍Unity常见存档系统二JSON以及使用方法
- 粗粒度和细粒度的区别
- java学习笔记————SSH
- 循环渐进NsDoor(一)
- matlab振动信号数据,Matlab在场地微振动信号数据处理中的应用
- android 爱普生打印机,安卓打印 爱普生推出智能iPrint新应用
- Vue.js入门学习--列表渲染--v-for遍历数组生成元素(四)
- Windows Server 2003 介绍
- 【HTML+CSS(六)】