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](三) ----- ...
随机推荐
- Python-垃圾回收机制
引子: 我们定义变量会申请内存空间来存放变量的值,而内存的容量是有限的,当一个变量值没有用了(简称垃圾)就应该将其占用的内存给回收掉,而变量名是访问到变量值的唯一方式,所以当一个变量值没有关联任何变量 ...
- 转:vue+element实现树形组件
项目中需要用到树形组件,在网上发现一个用vue+element实现的树形组件,现在记录下: demo地址:https://github.com/wilsonIs/vue-treeSelect
- bzoj1150 堆应用,好题
#include<bits/stdc++.h> using namespace std; #define maxn 100005 #define INF 0x3fffffff #defin ...
- plsql developer连接Oracle报错ORA-12154: TNS:could not resolve the connect identifier specified
今日更改Oracle网络配置文件后使用plsql developer 尝试连接到Oracle出现报错 ORA-12154: TNS:could not resolve the connect iden ...
- python 全栈开发,Day19(组合,组合实例,初识面向对象小结,初识继承)
一.组合 表示的一种什么有什么的关系 先来说一下,__init__的作用 class Dog: def __init__(self, name, kind, hp, ad): self.name = ...
- 《剑指offer》-前n项和不准用通解和各种判断
题目描述 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 这题目简直没事找事...为啥这么说,因为没有限 ...
- 【C++ Primer 第六章】 1. 定义模板
类模板 题目描述:实现StrBlob的模板版本. /* Blob.h */ #include<iostream> #include<vector> #include<in ...
- find算法
find(beg, end, val) :根据equal操作符,循序查找[first, last)内所有的元素,找出第一个匹配“等同条件者”.如果找到,就返回一个指向钙元素的迭代器,否者返回迭代器 ...
- HDU 3746 将字符串的全部字符最少循环2次需要添加的字符数
Sample Input3aaaabcaabcde Sample Output025 题目大意:给你一个字符串,要求将字符串的全部字符最少循环2次需要添加的字符数.例子:abcabc 已经循环2次,添 ...
- 如何批量的在django中对url进行用户登陆限制
参考URL: https://blog.csdn.net/hanshengzhao/article/details/79540306?utm_source=blogxgwz0 1,首先定义一个内部有装 ...