本系列主要參考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同一时候会加上一点个人理解或拓展。

这里是本书全部的插图。

这里是本书所需的代码和资源(当然你也能够从官网下载)。

========================================== 切割线 ==========================================

写在前面

通过上一篇我们建立了一个简化的屏幕特效系统,在这一篇,我们開始学习创建更复杂的像素操作来实现一些在当代游戏中常见的屏幕特效。

使用屏幕特效来调整游戏的总体色彩是非常重要的,这给了设计师控制游戏最后全貌的能力。

比方,通过颜色调整条来调整游戏终于画面的红蓝绿三色的密度,或者通过加入一定的色调使整个屏幕看起来像是老电影那样的效果。

这篇文章里,我们将会很多其它地学习关于调整图像颜色方面的内容。也就是,亮度、饱和度和对照度。学习这些调整颜色的方法能够让我们对屏幕特效有一个非常好的理解。

实现

这一篇非常多代码是建立在上一篇的基础上,所以非常多代码不用写啦~

  1. 创建一个新的脚本,命名为BSC_ImageEffect;
  2. 创建一个新的Shader。命名为BSC_Effect。
  3. 上一篇中的C#代码拷贝到第一步中创建的脚本中,我们仅仅须要关注亮度、饱和度和对照度效果的运算。
  4. 上一篇中的Shader代码拷贝到第二步中创建的Shader中。
  5. 把新的脚本加入到Camera上,并使用新的Shader给脚本中的Cur Shader赋值。
  6. 创建一个新的场景,命名为BSC_Effect。加入一个平行光,三个球体。以及一个平面。

    创建4个新材质,使用自带的Specular Shader就可以,随意选择四种颜色为它们赋值,这能够使我们更好地检验我们的画面特效。最后。把4个材质赋给球体和平面。

最后,你会得到相似于以下的效果:

实现

由于我们之前的代码已经完毕了建立一个主要的画面特效所需的核心操作,如今我们仅仅要完毕亮度、饱和度和对照度计算的代码就可以。
首先,我们来完毕Shader代码。
  1. 加入亮度、饱和度和对照度相应的新的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
    }
  2. 和曾经一样。在CGPROGRAM中建立和上述Properties之间的联系,创建相应的变量:
    	SubShader {
    Pass {
    CGPROGRAM
    #pragma vertex vert_img
    #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex;
    fixed _BrightnessAmount;
    fixed _SaturationAmount;
    fixed _ContrastAmoun
  3. 如今,我们须要创建操作来进行真正的亮度、饱和度和对照度的计算。在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的份重越大。

  4. 最后。我们须要略微改动下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;
    }
以下是编写脚本。我们须要在脚本中加入新的代码,以便能够向Shader发送合适的数据信息:
  1. 首先加入合适的变量来控制亮度、饱和度和对照度:
    	#region Variables
    public Shader curShader;
    public float brightnessAmount = 1.0f;
    public float saturationAmount = 1.0f;
    public float contrastAmount = 1.0f; private Material curMaterial;
    #endregion
  2. 然后,在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);
    }
    }
  3. 最后。我们仅仅须要在函数中,确保各变量的范围就可以。这些范围能够依据须要随意设置:
    	// 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);
    }
完毕后,返回Unity。我们这时能够在面板中更改亮度、饱和度和对照度了。

以下的图显示了它的结果:

  

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2FuZHljYXQxOTky/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

解释

相似这种屏幕特效对于得到高质量的游戏画面是非常重要的。它们同意你调整游戏的终于画面而不须要去编辑场景中全部的材质。

【Unity Shaders】使用Unity Render Textures实现画面特效——画面特效中的亮度、饱和度和对照度的更多相关文章

  1. 【Unity Shaders】Unity里的雾效模拟

    写在前面 熟悉Unity的都知道,Unity可以进行基本的雾效模拟.所谓雾效,就是在远离我们视角的方向上,物体看起来像被蒙上了某种颜色(通常是灰色).这种技术的实现实际上非常简单,就是根据物体距离摄像 ...

  2. 【Unity Shaders】使用Unity Render Textures实现画面特效——建立画面特效脚本系统

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  3. 【Unity Shaders】游戏性和画面特效——创建一个夜视效果的画面特效

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  4. 【Unity Shaders】游戏性和画面特效——创建一个老电影式的画面特效

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  5. 【Unity Shaders】Using Textures for Effects —— 实现Photoshop的色阶效果

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  6. 【Unity Shaders】Using Textures for Effects——打包和混合textures

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  7. 【Unity Shaders】Using Textures for Effects——让sprite sheets动起来

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  8. 【Unity Shaders】Using Textures for Effects——通过修改UV坐标来滚动textures

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  9. 【Unity Shaders】Using Textures for Effects介绍

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

随机推荐

  1. qt宽字符串中文乱码(codec->toUnicode值得学习)

    乱码原因: QT使用的是utf-8 简体中文版的windows操作系统及其应用软件默认都是ANSI/GBK编码.而且这里应该是宽字符串. 多字节ANISGB 宽字符UNICODE 多字节显示标准字符的 ...

  2. ListCtrl控件着色

    最近在写一款山寨的反病毒软件,大致功能已经实现,还有一些细小的环节需要细化. 其中,在界面编程中,就用到了给ListCtrl控件着色,查看了网上一些文章,终于实现了. 其实说白了,原理很简单,就是Li ...

  3. 图解UML类与类之间的六中关系

    大话设计模式上的一个图,我用EA画出来的:  UML中的6大关系相关英文及音标:  依赖关系 dependency [di'pendənsi]  关联关系 association  [ə,səuʃi' ...

  4. 【iOS】iOS的iTunes文件共享,在程序Document路径

    有时候程序开发须要通过沙盒中的 documents目录与用户共享文件,iTunes默认是不支持iTunes file Sharing的,首先设置 info-list的Application suppo ...

  5. MongoDB学习笔记(一)

    MongoDB的介绍我就不说了.直接开始环境的搭建和连接.在这个之前,向大家介绍几个关于MongoDB的网站. 1.  https://www.mongodb.com/ MongoDB的官网. 2. ...

  6. XML和对象属性互转的基类

    本人做了一个XML和对象属性互转的基类,现在放上来有兴趣拿去看一下,用法很简单,声明一个BaseConversion的子类,该子类与你想转换的对象相对应,然后覆盖基类的两个虚方法,然后在里面写元素与对 ...

  7. urllib2的异常处理

    异常处理 作为爬虫的抓取过程基本就那么多内容了,后面再将一些正则表达式的东西简单介绍一下基本就完事了,下面先说说异常处理的方法.先介绍一下抓取过程中的主要异常,如URLError和HTTPError. ...

  8. Linux $( )与${ }的区别

    初学者也许会遇到这个问题~ $( )的用途和反引号` `一样,用来表示优先执行的命令,比如ls -l $(locate build.xml),表示先找到build.xml的位置,然后再列出详细信息. ...

  9. 总结showModalDialog在开发中的一些问题

    一.在页面调用window.open()函数后,可以直接在打开的页面中用window.opener来调用父页面的方法,然而如果用showModalDialog打开一个模态窗口,就不能通过window. ...

  10. linux-sfdisk 使用方法

    功能说明:硬盘分区工具程序. 语 法:sfdisk [-?Tvx][-d <硬盘>][-g <硬盘>][-l <硬盘>][-s <分区>][-V < ...