| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> 【Unity Shader】从数值角度分析颜色调整(亮度、对比度和饱和度) -> 正文阅读 |
|
[游戏开发]【Unity Shader】从数值角度分析颜色调整(亮度、对比度和饱和度) |
第一次写博客。 因为前段时间看《Unity Shader入门精要》时,不理解12章第2节中luminance值计算公式的原理,书中也没有对此进行详尽解释,同时在网上也很难查阅到相关的资料。但在查阅了一些数字图像处理相关的知识后,也终于理解了其中的原理,所以打算写篇博客分享一下我个人对此的理解。 一、颜色模型因为网上有很多关于颜色模型相关概念、知识的资料,所以在此我就不做详细介绍了,在这只简单介绍一下本文的主角RGB颜色模型。 RGB全称是Red、Green、Blue,即红绿蓝三色,是最常见最常用的三原色。通过混合不同比例的红绿蓝三原色,可以得到自然界中我们能看到的绝大多数颜色。 为了方便定义混色的比例,同时因为在给颜色分级的时候大部分芯片是八位的,所以把每种颜色按亮度分为0~255共256个等级,即RGB值。 RGB值越小时,对应颜色越暗;RGB值越大时,对应颜色越亮。因此不难理解为什么RGB(0,0,0)是黑色,RGB(255,255,255)是白色。 在Unity Shader中,把RGB值从[0,255]映射到了[0,1]之中,套用??1÷256×对应颜色RGB值? 计算公式,同时采用??2舍3入??的计数保留法就能得到该颜色在Unity中的数值表示。 举个栗子: 1、首先在PS中随便调一个不常见的颜色 2、然后使用上面的公式计算这个颜色RGB值在Unity Shader中的映射值 R: 1/256*124 ≈ 0.485 3、接着在Unity Shdaer的片元着色器中直接输出这三个值 ?4、下图是该颜色值在Unity中的显示,大家可以用截屏软件在截屏时自带的RGB吸色功能对比一下两张色图()的RGB值是否是一致的。 二、Unity Shader的Lerp()函数在正式讲解亮度、饱和度和对比度的调整原理前,先来聊聊Unity Shader中Lerp()函数这个坑。关于Lerp()函数公式在这里就不做过多的解释了,网上也有很多相关资料。
这里主要想说的是这个函数输入值w的区间与其他大多数博客中所说的根本就不一样! 只要在搜索引擎中搜索“unity lerp函数”,查到的博客、资料都会跟你说w值只能是0~1之间的数,有的博客还会说如果你输入的w值超出了[0,1],就会被限制为0或者1。 所以我当时就很懵,因为在《Unity Shader入门精要》中输入的w值都超过了[0,1]这个区间 ?后来我发现,其实Unity Shader中的Lerp()函数是把a~b之间的差值等分为了无数份,这是因为0~1之间能等分为多少份不可估量。这时就能根据w值在[0,1]中的什么位置,来定义Lerp()应该输出什么值。 当w<0时,输出的值就是 输入值a减去每一份的差值;当w>1时,输出的值就是 输入值b加上每一份的差值。也就是因为Lerp()函数有这个独特的性质,才能用来调整颜色的亮度、饱和度和对比度。 三、亮度从最简单的亮度开始分析。
上文说到[0,255]这256个等级是每种颜色的亮度等级,同时Unity Shader把RGB值从[0,255]映射到了[0,1]。 因此不难理解此处的代码实则是对对应像素的RGB值进行了一个统一缩放,在保证了三原色的混合比例不变的情况下,改变了对应颜色的明暗度。 四、对比度?对比度,实际上指的是一个画面中显示的? RGB值最大的像素? 与? RGB值最小的像素? 之间的差值的大小,也就是最亮的像素与最暗的像素之间的差值,因此称为对比度。
此处使用fixed3(0.5, 0.5, 0.5)是因为0.5是[0,1]之间的中值,使用0.5对原RGB值进行插值。 当_Contrast<1时,画面中所有的像素RGB值都会越来越接近0.5。此时画面中最亮的像素与最暗的像素之间的差值就逐渐减小,也就是对比度逐渐变小; 当_Contrast>1时,画面中所有的像素RGB值都会离0.5越来越远,此时画面中最亮的像素与最暗的像素之间的差值就逐渐增大,也就是对比度逐渐变大。 这也是PS中的旧版对比度算法原理。 五、饱和度“纯度是指色彩的纯净程度,也就是色彩的饱和度。物体的饱和度取决于该物体表面选择性的反射能力。在同一色相中添加白色、黑色或灰色都会降低它的纯度。” --《平面设计配色从入门到精通》曹茂鹏
因为有Lerp()函数的存在,只要我们能得到目标像素饱和度为0时的RGB值,当_Saturation>1时,利用Lerp()函数的性质,就能起到增大目标像素颜色饱和度的作用。 由上面的饱和度概念可推,往一种颜色中添加大量的黑白灰色,当该颜色中的黑白灰色的量远大于原颜色的量时,可以认为该颜色的灰度值就是该颜色饱和度为0时的RGB值。因此,当一个画面饱和度为0时,得到的应该是该画面对应的灰度图。 PS中的饱和度调整: 代码中luminance值的计算公式求的就是目标像素RGB颜色值对应的灰度等级。 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b 对于这条公式,我后来查找到该公式是RGB转YUV的BT709明亮度转换公式,是基于人眼感知的图像灰度处理公式。这条公式通过计算每个像素RGB值对应的灰度值,来把RGB彩色图像转换为灰度图。 YUV颜色模型起初是用于解决彩色电视和黑白电视兼容性问题,其中的Y值表示明亮度,也是灰阶值,这里的luminance值其实就是这个Y值。 对于这个公式的三个系数为什么不是0.5,0.5,0.5,而是0.2125,0.7154,0.0721。那是因为人眼对红绿蓝三色的敏感程度不同,所以计算灰度的时候要加权平均。这个系数主要是根据人眼对R,G,B三原色的敏感性不同而导出的系数。如果想知道更多详细信息可以查阅“色度学”相关资料。 类似的,还有如下公式: Y?= 0.299*R?+ 0.587*G?+ 0.114*B 虽然这条公式与上一条公式在系数上有很大的不同,但是实际上得到的灰度图结果仅以我们人类肉眼来看,很难看出其中的不同。因此,在计算一个画面时,使用上面哪条公式都是OK的。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/28 0:47:40- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |