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](三) ----- ...
随机推荐
- Linux查看文件命令
linux查看日志文件内容命令有 cat 由第一行开始显示文件内容 tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写 nl 显示的时候,顺道输出行号! more 一页一页的显示文件内 ...
- Node.js随手笔记
参考文章:https://blog.csdn.net/IronKee/article/details/83780857 安装nvm的方法: 如果已经单独安装了node,建议卸载,然后继续向下看. 直接 ...
- css怎么让页面上的内容不能被选中
body{ -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-se ...
- LeetCode(44): 通配符匹配
Hard! 题目描述: 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配. '?' 可以匹配任何单个字符. '*' 可以匹配任意字符串(包括空字符串). ...
- poj1015 01二维背包
/* 给定辩控双方给每个人的打分p[i],d[i], dp[j][k]表示前i个人有j个被选定,选定的人的辩控双方打分差之和是k,此状态下的最大辩控双方和 按01背包做,体积一维是1,体积二维是辩控双 ...
- hdu1698
/*区间更新*/#include <cstdio> #include <algorithm> using namespace std; #define lson l , m , ...
- HDU1730 Northcott Game 尼姆博弈
Northcott Game Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- android Unable to inflate view tag without class attribute
定位 到 问题 是 布局文件出错, Unable to inflate view tag without class attribute 错误 原因 <view android:layout ...
- 《Kafka技术内幕》学习笔记
第一章 Kafka入门 1.1 Kafka流式数据平台 Kafka作为流式数据平台的特点: 消息系统:两种消息模型:队列和发布订阅. 队列模型:将处理工作平均分给消费组中的消费者成员. 发布订阅模型: ...
- 使用Maven进行多模块拆分
模块拆分是Maven经常使用的功能,简单梳理一下如何使用Maven进行多模块拆分, 只做归纳总结,网上资料很多,不再一步一步实际创建和部署. 建立Maven多模块项目 一个简单的Java Web项目, ...