博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Mobile里实现Linear Rendering
阅读量:5049 次
发布时间:2019-06-12

本文共 1114 字,大约阅读时间需要 3 分钟。

Linear Rendering的意义就不用多说了,Unity的文档中说得非常清楚。

首先看看人眼对亮度感知的函数曲线。这里取最常见的参数2.2

y=power(x, 2.2)

 

横轴是亮度,纵轴是人眼感知到的亮度。

美术用所见即所得的方式调出来的贴图,实际像素都是被曲线所影响过的,

光照如果也在Gamma空间内计算,相当于也同样受这个曲线影响,结果就是亮部更亮。(LDR管线这个问题更加突出,因为超过1的像素都被一刀切成1了)

我们看看Unity提供的参考效果对比图:

 

 

实际在项目中,如果用Gamma空间,美术调亮一点贴图,亮部就会大面积过爆,而调暗一点,暗部就会太黑。非常难以调整。

有时候美术就会调整光照环境,或者要求增加一个光源来给暗部补光。这会带来额外的性能开销,尤其Unity的Forward Rendering会增加一个ForwardAdd pass。

最关键的问题是,用一个错误弥补另一个错误是不对的,只会越来越乱。

 

硬件实现的LinearRendering的方法是:

1.标记处贴图是否在Gamma空间(sRGB)。

2.shader内采样sRGB时,硬件做一个pow(2.2)操作

3.在线性空间内进行光照计算

4.全部shading完成后,在LDR做pow(1/2.2),转成Gamma空间显示。

 

根据上面的流程,可以自己在shader中实现

1. 采完颜色贴图后,做pow(2.2)

2. 所有光源同样做pow(2,2)处理

3. 最终输出光照结果时,做pow(1/2.2)(对于LDR)

 

其中1可以利用Unity的AssetPostProcessor来做。变成在导入颜色贴图时(可以用命名规范来识别),逐像素做pow(2.2)。shader中在linear space做光照计算,最后补个gamma correction的后处理。

 

测试后发现,上述方法只适用于较亮的贴图。暗的贴图会出现严重的banding artifact。这是因为pow(2.2)之后暗部会被压缩,rgb8的精度有限,细微的变化就损失掉了。引擎中打光会提亮暗部,暴露缺陷。

 

所以不能直接修改贴图的像素,只能回归shader方案,进行优化。pow(2.2)可以用简单的平方代替,这样

1. shader采样sRGB后,做平方计算

2.光源亮度,色块等可以提前做好平方,传入gpu

3.补上pow(0.5)的gamma校正

效果与unity自带的linear rendering几乎一样,并且不用担心兼容性,gles2.0上也可以运行。

转载于:https://www.cnblogs.com/cpxnet/p/6207666.html

你可能感兴趣的文章
学习python:day1
查看>>
css3动画属性
查看>>
第九次团队作业-测试报告与用户使用手册
查看>>
Equal Sides Of An Array
查看>>
CentOS笔记-用户和用户组管理
查看>>
Mongodb 基本命令
查看>>
Qt中QTableView中加入Check列实现
查看>>
“富豪相亲大会”究竟迷失了什么?
查看>>
控制文件的备份与恢复
查看>>
返回代码hdu 2054 A==B?
查看>>
Flink独立集群1
查看>>
iOS 8 地图
查看>>
20165235 第八周课下补做
查看>>
[leetcode] 1. Two Sum
查看>>
iOS 日常工作之常用宏定义大全
查看>>
PHP的SQL注入技术实现以及预防措施
查看>>
MVC Razor
查看>>
软件目录结构规范
查看>>
Windbg调试Sql Server 进程
查看>>
linux调度器系列
查看>>