Unity Shader-后处理:简单的颜色调整(亮度,饱和度,对比度)
好久没坚持写blog了,是时候开始撸一波新博文了!学习Unity有一段时间了,关于Shader的书也看了几本《Unity Shader入门精要》,《Unity 3D ShaderLab 开发实战详解》,开一个系列记录一下学习的心得笔记。原理就不多讲了,一篇一个实际Shader样例就好了。
貌似一开始关于shader的讲解都是diffuse,不过,我赶脚后处理貌似更简单,所以第一篇来一发简单后处理,屏幕的简单颜色校正--调整亮度,饱和度,对比度。
一.概念介绍
1.颜色模型的概念
1.1RGB颜色模型
1.2HSV颜色模型
1.3RGB颜色模型和HSV颜色模型的转化
2.亮度,饱和度,对比度,灰度的概念
2.1亮度
2.2饱和度
2.3对比度
2.4灰度
二.Unity屏幕后处理原理
1.OnRenderImage函数
- void OnRenderImage(RenderTexture sourceTexture,RenderTexture destTexture);
RenderTexture表示的是渲染纹理,我们渲染物体并不是仅仅渲染在屏幕空间,也可以将物体渲染到特定纹理上,也就是RenderTexture。sourceTexture就是我们渲染的场景图片,而destTexture是目标渲染纹理。我们可以在这个函数中进行相关的后处理效果,使用带有后处理效果shader的材质将场景内容重新渲染。
2.Graphics.Blit函数
- public static void Blit(Texture source,RenderTexture dest);
- public static void Blit(Texture source,RenderTexture dest, Material mat, int pass = -1);
- public static void Blit(Texture source,Material mat, int pass = -1);
source是源纹理,dest是目标纹理,当dest为null时,直接将源纹理拷贝到屏幕;mat是拷贝时使用的材质,也就是我们后处理时使用的材质,Unity会使用该材质将源纹理进行处理拷贝给目标纹理,pass是使用的材质shader所使用的pass,我们知道,一个shader中可能有多个pass,使用哪个pass进行处理就可以从该参数传入,当然,默认为-1时表示所有的pass都会执行。
三.后处理效果代码
1.脚本部分
- using UnityEngine;
- using System.Collections;
- //非运行时也触发效果
- [ExecuteInEditMode]
- //屏幕后处理特效一般都需要绑定在摄像机上
- [RequireComponent(typeof(Camera))]
- //提供一个后处理的基类,主要功能在于直接通过Inspector面板拖入shader,生成shader对应的材质
- public class PostEffectBase : MonoBehaviour {
- //Inspector面板上直接拖入
- public Shader shader = null;
- private Material _material = null;
- public Material _Material
- {
- get
- {
- if (_material == null)
- _material = GenerateMaterial(shader);
- return _material;
- }
- }
- //根据shader创建用于屏幕特效的材质
- protected Material GenerateMaterial(Shader shader)
- {
- if (shader == null)
- return null;
- //需要判断shader是否支持
- if (shader.isSupported == false)
- return null;
- Material material = new Material(shader);
- material.hideFlags = HideFlags.DontSave;
- if (material)
- return material;
- return null;
- }
- }
- using UnityEngine;
- using System.Collections;
- //继承自PostEffectBase
- public class ColorAdjustEffect : PostEffectBase {
- //通过Range控制可以输入的参数的范围
- [Range(0.0f, 3.0f)]
- public float brightness = 1.0f;//亮度
- [Range(0.0f, 3.0f)]
- public float contrast = 1.0f; //对比度
- [Range(0.0f, 3.0f)]
- public float saturation = 1.0f;//饱和度
- //覆写OnRenderImage函数
- void OnRenderImage(RenderTexture src, RenderTexture dest)
- {
- //仅仅当有材质的时候才进行后处理,如果_Material为空,不进行后处理
- if (_Material)
- {
- //通过Material.SetXXX("name",value)可以设置shader中的参数值
- _Material.SetFloat("_Brightness", brightness);
- _Material.SetFloat("_Saturation", saturation);
- _Material.SetFloat("_Contrast", contrast);
- //使用Material处理Texture,dest不一定是屏幕,后处理效果可以叠加的!
- Graphics.Blit(src, dest, _Material);
- }
- else
- {
- //直接绘制
- Graphics.Blit(src, dest);
- }
- }
- }
这样,我们的后处理脚本就完成了。涉及到以下几个知识点:
2.shader部分
- //shader的目录
- Shader "Custom/ColorAdjustEffect"
- {
- //属性块,shader用到的属性,可以直接在Inspector面板调整
- Properties
- {
- _MainTex ("Albedo (RGB)", 2D) = "white" {}
- _Brightness("Brightness", Float) = 1
- _Saturation("Saturation", Float) = 1
- _Contrast("Contrast", Float) = 1
- }
- //每个shader都有Subshaer,各个subshaer之间是平行关系,只可能运行一个subshader,主要针对不同硬件
- SubShader
- {
- //真正干活的就是Pass了,一个shader中可能有不同的pass,可以执行多个pass
- Pass
- {
- //设置一些渲染状态,此处先不详细解释
- ZTest Always Cull Off ZWrite Off
- CGPROGRAM
- //在Properties中的内容只是给Inspector面板使用,真正声明在此处,注意与上面一致性
- sampler2D _MainTex;
- half _Brightness;
- half _Saturation;
- half _Contrast;
- //vert和frag函数
- #pragma vertex vert
- #pragma fragment frag
- #include "Lighting.cginc"
- //从vertex shader传入pixel shader的参数
- struct v2f
- {
- float4 pos : SV_POSITION; //顶点位置
- half2 uv : TEXCOORD0; //UV坐标
- };
- //vertex shader
- //appdata_img:带有位置和一个纹理坐标的顶点着色器输入
- v2f vert(appdata_img v)
- {
- v2f o;
- //从自身空间转向投影空间
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- //uv坐标赋值给output
- o.uv = v.texcoord;
- return o;
- }
- //fragment shader
- fixed4 frag(v2f i) : SV_Target
- {
- //从_MainTex中根据uv坐标进行采样
- fixed4 renderTex = tex2D(_MainTex, i.uv);
- //brigtness亮度直接乘以一个系数,也就是RGB整体缩放,调整亮度
- fixed3 finalColor = renderTex * _Brightness;
- //saturation饱和度:首先根据公式计算同等亮度情况下饱和度最低的值:
- fixed gray = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
- fixed3 grayColor = fixed3(gray, gray, gray);
- //根据Saturation在饱和度最低的图像和原图之间差值
- finalColor = lerp(grayColor, finalColor, _Saturation);
- //contrast对比度:首先计算对比度最低的值
- fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
- //根据Contrast在对比度最低的图像和原图之间差值
- finalColor = lerp(avgColor, finalColor, _Contrast);
- //返回结果,alpha通道不变
- return fixed4(finalColor, renderTex.a);
- }
- ENDCG
- }
- }
- //防止shader失效的保障措施
- FallBack Off
- }
四.效果展示
Unity Shader-后处理:简单的颜色调整(亮度,饱和度,对比度)的更多相关文章
- glsl计算sprite的亮度饱和度对比度
//glsl计算sprite的亮度饱和度对比度 #ifdef GL_ES precision mediump float; #endif uniform sampler2D u_texture; va ...
- Unity Shader后处理-搜索灰度效果
如U3D中Hierarchy面板下的搜索效果: 讲解分析: 1.这种PostEffect效果其实就是指Unity shader的后处理,即游戏中实现屏幕特效的常见方法.顾名思义屏幕后处理就是指在渲染完 ...
- unity shader 剔除指定的颜色
Shader "MyShader/PaintingBGTransparency" { Properties{ _MainTex("Base (RGB)", 2D ...
- Unity Shader入门精要学习笔记 - 第12章 屏幕后处理效果
建立一个基本的屏幕后处理脚本系统 屏幕后处理,顾名思义,通常指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效.使用这种技术,可以为游戏画面添加更多艺术效果,例如景深. ...
- 【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨) ...
- 【转】《Unity Shader入门精要》冯乐乐著 书中彩图
为方便个人手机学习时候查阅,从网上转来这些彩图. 如属过当行为,联系本人删除. 勘错表 http://candycat1992.github.io/unity_shaders_book/unity_s ...
- Unity Shader入门精要学习笔记 - 第10章 高级纹理
转载自 冯乐乐的 <Unity Shader入门精要> 立方体纹理 在图形学中,立方体纹理是环境映射的一种实现方法.环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像镀了层 ...
- Unity Shader入门精要之 screen post-processing effect
本篇记录了学习Unity Shader入门精要的屏幕后处理的一些知识点. OnRenderImage(RenderTexture src, RenderTexture dest) 以上函数是Unity ...
- 【Unity Shader】(十) ------ UV动画原理及简易实现
笔者使用的是 Unity 2018.2.0f2 + VS2017,建议读者使用与 Unity 2018 相近的版本,避免一些因为版本不一致而出现的问题. [Unity Shader](三) ----- ...
随机推荐
- Day6-------------ext4文件系统
1.cp /etc/passwd /sdb6 把/etc/passwd的内容写入 sdb6 写入过程:日志------------>刷到硬盘 2.ext4已经有点过时 xfs:可存海量数据 bt ...
- mysql 常用,使用经验
mysql default boolean字段 `enable` char(1) NOT NULL DEFAULT '1' COMMENT '启(禁)用',结果: this.enable ? &qu ...
- 将数据库从Oracle迁移到SQL Server
参考链接:http://www.360doc.com/content/15/0310/14/9260775_454038517.shtml
- 分享我对JS插件开发的一些感想和心得
本文阅读目录: •起因•如何开发一个轻量级的适用性强的插件•总结 起因 如果大家平时做过一些前端开发方面的工作,一定会有这样的体会:页面需要某种效果或者插件的时候,我们一般会有两种选择: 1.上网查找 ...
- 搭建ssh框架项目(二)
一.创建dao层 (1)创建接口ICommonDao.java package com.cppdy.ssh.dao; public interface ICommonDao<T> { pu ...
- laravel 事件广播
Laravel 5.1 之中新加入了事件广播的功能,作用是把服务器中触发的事件通过websocket服务通知客户端,也就是浏览器,客户端js根据接受到的事件,做出相应动作.本文会用简单的代码展示一个事 ...
- Python 定值类
1.__str__和__repr__ 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class Person(object): def __init__(self, nam ...
- java List.subList方法中的超级大陷阱
ArrayList 中 subList 的基本用法: subList(fromIndex:int,toIndex:int):List<E> 返回从fromIndex到toindex-1 的 ...
- DDD领域模型AutoMapper实现DTO(七)
DTO的应用场景: 定义产品类: public class Product { public string ProductName { get; set; } public decimal Produ ...
- mysql_union操作符
MySQL UNION操作符 union操作符合并两个或多个 SELECT 语句的结果集. union:去重 union all:不去重 UNION 结果集中的列名总是等于 UNION 中第一个 S ...