【Unity Shaders】使用Unity Render Textures实现画面特效——画面特效中的亮度、饱和度和对照度
本系列主要參考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同一时候会加上一点个人理解或拓展。
这里是本书全部的插图。
========================================== 切割线 ==========================================
写在前面
通过上一篇我们建立了一个简化的屏幕特效系统,在这一篇,我们開始学习创建更复杂的像素操作来实现一些在当代游戏中常见的屏幕特效。
使用屏幕特效来调整游戏的总体色彩是非常重要的,这给了设计师控制游戏最后全貌的能力。
比方,通过颜色调整条来调整游戏终于画面的红蓝绿三色的密度,或者通过加入一定的色调使整个屏幕看起来像是老电影那样的效果。
这篇文章里,我们将会很多其它地学习关于调整图像颜色方面的内容。也就是,亮度、饱和度和对照度。学习这些调整颜色的方法能够让我们对屏幕特效有一个非常好的理解。
实现
这一篇非常多代码是建立在上一篇的基础上,所以非常多代码不用写啦~
- 创建一个新的脚本,命名为BSC_ImageEffect;
- 创建一个新的Shader。命名为BSC_Effect。
- 把上一篇中的C#代码拷贝到第一步中创建的脚本中,我们仅仅须要关注亮度、饱和度和对照度效果的运算。
- 把上一篇中的Shader代码拷贝到第二步中创建的Shader中。
- 把新的脚本加入到Camera上,并使用新的Shader给脚本中的Cur Shader赋值。
- 创建一个新的场景,命名为BSC_Effect。加入一个平行光,三个球体。以及一个平面。
创建4个新材质,使用自带的Specular Shader就可以,随意选择四种颜色为它们赋值,这能够使我们更好地检验我们的画面特效。最后。把4个材质赋给球体和平面。
实现
- 加入亮度、饱和度和对照度相应的新的Properties,我们要保留_MainTex属性,这是由于在创建画面特效时。该属性就是脚本传递给我们的render texture。
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_BrightnessAmount ("Brightness Amount", Range(0.0, 2.0)) = 1.0
_SaturationAmount ("Saturation Amount", Range(0.0, 1.0)) = 1.0
_ContrastAmount ("Contrast Amount", Range(0.0, 1.0)) = 1.0
} - 和曾经一样。在CGPROGRAM中建立和上述Properties之间的联系,创建相应的变量:
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex;
fixed _BrightnessAmount;
fixed _SaturationAmount;
fixed _ContrastAmoun - 如今,我们须要创建操作来进行真正的亮度、饱和度和对照度的计算。在frag函数上面创建以下的函数:
float3 ContrastSaturationBrightness (float3 color, float brt, float sat, float con) {
// Increase or decrease these values to
// adjust r, g and b color channels separately
float avgLumR = 0.5;
float avgLumG = 0.5;
float avgLumB = 0.5; // Luminance coefficients for getting luminance from the image
float3 LuminanceCoeff = float3 (0.2125, 0.7154, 0.0721); // Operation for brightmess
float3 avgLumin = float3 (avgLumR, avgLumG, avgLumB);
float3 brtColor = color * brt;
float intensityf = dot (brtColor, LuminanceCoeff);
float3 intensity = float3 (intensityf, intensityf, intensityf); // Operation for saturation
float3 satColor = lerp (intensity, brtColor, sat); // Operation for contrast
float3 conColor = lerp (avgLumin, satColor, con); return conColor;
}解释:这个函数的第一个參数是当前的render texture的某个像素。其它參数则是用于总体调整颜色,这些变量会通过后面的脚本传递给Shader。
函数一開始。声明了一些常量。它们被用于定义一个最主要的颜色值,以便和改动后的进行比較。
书上讲这个函数的实现的地方比較含糊不清,看不懂。我按自己的理解解释一下。这事实上是一个叠加的过程:先计算当前亮度值下的像素,再在此基础上计算当前饱和度值下的像素。最后再在此基础上计算当前对照度下的像素,并输出:
—— 当前亮度值下的像素是通过使用render texture上原始的像素乘以亮度值实现的,这非常好理解,brt越大(能够大于1),图像越偏向白色,也就越亮。—— 计算当前饱和度值下的像素。须要使用lerp函数。当中,lerp的右边界值就是上一步得到的像素值,而左边界值是当前亮度下饱和度最低的像素值。计算方法是在当前亮度的基础上,点乘LuminanceCoeff常量系数。这些系数是基于CIE颜色匹配函数的,也是业界公认的标准。
最后,sat參数在两者之间进行线性插值。sat越大(能够大于1),brtColor的份重越大。
—— 计算当前对照度下的像素是相似的过程。相同使用lerp函数。当中。lerp的右边界是上一步得到的像素值,左边界值是对照度最低的像素值。这里使用了常量avgLumin。最后,con參数在两者之间进行线性插值。
con越大(能够大于1),satColor的份重越大。
- 最后。我们须要略微改动下frag函数。使得它能够逐像素处理render texture中的每一个像素。然后再又一次输出,返回给脚本:
fixed4 frag(v2f_img i) : COLOR {
//Get the colors from the RenderTexture and the uv's
//from the v2f_img struct
fixed4 renderTex = tex2D(_MainTex, i.uv); //Apply the brightness, saturation, contrast operations
renderTex.rgb = ContrastSaturationBrightness (renderTex.rgb, _BrightnessAmount, _SaturationAmount, _ContrastAmount); return renderTex;
}
- 首先加入合适的变量来控制亮度、饱和度和对照度:
#region Variables
public Shader curShader;
public float brightnessAmount = 1.0f;
public float saturationAmount = 1.0f;
public float contrastAmount = 1.0f; private Material curMaterial;
#endregion - 然后,在OnRenderImage函数中。将新的值传递给Shader:
void OnRenderImage (RenderTexture sourceTexture, RenderTexture destTexture){
if (curShader != null) {
material.SetFloat("_BrightnessAmount", brightnessAmount);
material.SetFloat("_SaturationAmount", saturationAmount);
material.SetFloat("_ContrastAmount", contrastAmount); Graphics.Blit(sourceTexture, destTexture, material);
} else {
Graphics.Blit(sourceTexture, destTexture);
}
} - 最后。我们仅仅须要在函数中,确保各变量的范围就可以。这些范围能够依据须要随意设置:
// Update is called once per frame
void Update () {
brightnessAmount = Mathf.Clamp(brightnessAmount, 0.0f, 2.0f);
saturationAmount = Mathf.Clamp(saturationAmount, 0.0f, 2.0f);
contrastAmount = Mathf.Clamp(contrastAmount, 0.0f, 3.0f);
}
以下的图显示了它的结果:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2FuZHljYXQxOTky/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />
解释
【Unity Shaders】使用Unity Render Textures实现画面特效——画面特效中的亮度、饱和度和对照度的更多相关文章
- 【Unity Shaders】Unity里的雾效模拟
写在前面 熟悉Unity的都知道,Unity可以进行基本的雾效模拟.所谓雾效,就是在远离我们视角的方向上,物体看起来像被蒙上了某种颜色(通常是灰色).这种技术的实现实际上非常简单,就是根据物体距离摄像 ...
- 【Unity Shaders】使用Unity Render Textures实现画面特效——建立画面特效脚本系统
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】游戏性和画面特效——创建一个夜视效果的画面特效
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】游戏性和画面特效——创建一个老电影式的画面特效
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Using Textures for Effects —— 实现Photoshop的色阶效果
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Using Textures for Effects——打包和混合textures
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Using Textures for Effects——让sprite sheets动起来
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Using Textures for Effects——通过修改UV坐标来滚动textures
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Using Textures for Effects介绍
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
随机推荐
- MFC实现多风格真彩色大图标工具栏按钮
研究zlib库,想实现一个类似winrar功能的小东东,打开winrar界面看它的工具栏比较好看于是动手想做一个,当然资源也使用的是winrar附带的.下面是截图:真彩色(32位)32*32大图标工具 ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(三)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(三) Lucene有表达式就有运算符,而运算符使用起来确实很方便,但另外一个问题来了. 代码 4.3.4.1 Analyzer anal ...
- uva 10131 Is Bigger Smarter?(DAG最长路)
题目连接:10131 - Is Bigger Smarter? 题目大意:给出n只大象的属性, 包括重量w, 智商s, 现在要求找到一个连续的序列, 要求每只大象的重量比前一只的大, 智商却要小, 输 ...
- Mina2 研究总结
一.Mina框架. Mina的框架大概是这么个样子: 底层由Java 的NIO 1.0实现 核心架构应该是这样: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZX ...
- 使用svnkit 的相关实例及相关问题汇总
SVNKIT操作SVN版本库的完整例子 http://www.cnblogs.com/wangjiyuan/p/svnkitwanchenglizi.html#!comments 2.SVNClien ...
- apk应用的反编译和源代码的生成
对于反编译一直持有无所谓有或无的态度.经过昨天一下午的尝试,也有了点心得和体会: 先给大家看看编译的过程和我们反编译的过程概图吧: 例如以下是反编译工具的根文件夹结构: 三个目录也实际上是下面三个步骤 ...
- [docker]docker的四种网络方式
声明: 本博客欢迎转发,但请保留原作者信息! 博客地址:http://blog.csdn.net/halcyonbaby 内容系本人学习.研究和总结,如有雷同,实属荣幸! bridge方式(默认) H ...
- 使用Boost库中的组件进行C++内存管理
C++标准库中的auto_ptr,智能指针,部分的解决了获取资源自动释放的问题 在Boost中,提供了6中智能指针:scoped_ptr, scoped_array, shared_ptr, shar ...
- 使用Seam Framework + JBoss 5.0 开发第一个Web应用 - 简单投票程序
Seam这个单词的本意是缝合.连接,因而,Seam的作用即是把Java EE 规范里的JSF 和 EJB技术完美融合在一起,免去了很多胶合代码,并增强了JSF 和 EJB的很多功能.Seam的设计目标 ...
- ios应用接入微信开放平台
前几天试了一下服务端接入微信公众平台,昨天又看了一下APP接入开放平台 开放平台和公众平台的差别 公众平台针对的是公众账号,除了提供管理后台之外.也开放了若干接口,让微信server和开发人员自己的应 ...