亮度、饱和度、对比度
在屏幕后处理的Shader中 需要设置深度测试、剔除、深度写入 - ZTest Always 打开深度测试 - Cull Off 关闭剔除 - ZWrite Off 关闭深度写入 主要是避免它"挡住"后面的渲染物体
1.基本原理
1.亮度
想要改变颜色的亮度
只需要对图像的每个像素点进行加法运算或乘法运算即可
也就是说,我们只需要在Shader当中加入一个控制亮度的float类型的变量
然后用颜色的RGB乘以该变量即可
一般我们会采用乘法的形式
即:
最终颜色 = 源颜色 * 亮度变量
2.饱和度
想要改变颜色的饱和度
只需要对图像的每个像素的颜色值 相对于灰度颜色进行插值来实现
基本原理如下: 1. 计算灰度值
利用图像的颜色RGB计算一个平均值,得到一个灰度值
但是由于人眼对不同的颜色敏感程度不同,所以一般不会直接计算平均值
图形学中一般使用加权平均法来计算灰度值
常用的权重基于Rec,790标准(高清电视和许多数字图像格式中常用标准) - R 红色通道权重 0.2126 - G 绿色通道权重 0.7152 - B 蓝色通道权重 0.0722
所以计算灰度值公式:
灰度值L = 0.2126 * R + 0.7152 * G + 0.0722 * B 2. 生成灰度颜色
利用第一步中计算出来的灰度值,生成一个灰度颜色
灰度颜色 = (L,L,L) 3. 插值计算
使用插值函数,在灰度颜色和原始颜色之间进行插值计算
插值系数就是用于控制饱和度的float类型变量
最终颜色 = lerp(灰度颜色,源颜色,饱和度变量) - 饱和度变量=0时,结果为灰度颜色 - 饱和度变量=1时,保持原始颜色不变 - 饱和度变量=0~1之间时,灰度颜色和原始颜色的混合 - 饱和度变量 >1时,颜色的RGB值超出原始范围,从而使颜色看起来更饱和
3.对比度
想要改变图像颜色的的对比度
只需要对图像的每个像素的颜色值 相对于中性灰色进行插值来实现
基本原理: 1. 声明中性颜色变量 即:RGB都为0.5的颜色变量
中性颜色 = (0.5,0.5,0.5) 2. 插值计算
使用插值函数,在灰度颜色和原始颜色之间进行插值计算
插值系数就是用于控制对比度的float类型变量
最终颜色 = lerp(中性颜色,源颜色,对比度变量) - 对比度变量 = 0 时,此时对比度降到最低,变为中性灰色 - 对比度变量 = 1时,保持原始颜色不变 - 对比度变量 0~1 之间时,降低对比度效果,图像的亮度差异减少,使图像颜色看起来更平淡 - 对比度变量 >1时,颜色的RGB值超出原始范围,从而使颜色亮部更亮,暗部更暗,从而增加对比度
2.实现示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| Shader "Unlit/BrightnessSaturationContrast" { Properties { _MainTex ("Texture", 2D) = "white" {} //亮度变量 _Brightness("Brightness",Float) = 1 //饱和度变量 _Saturation("Sturation",Float) = 1 //对比度变量 _Contrast("Contrast",Float) = 1 } SubShader { Tags{"RenderType"="Opaque"} Pass { //这三个设置是屏幕后处理的标配 ZTest Always Cull Off ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc"
struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; };
sampler2D _MainTex; float4 _MainTex_ST; half _Brightness; half _Saturation; half _Contrast; v2f vert(appdata_base v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord,_MainTex); return o; }
fixed4 frag(v2f i) : SV_Target { //从捕获的主纹理进行采样 fixed4 renderTexColor = tex2D(_MainTex, i.uv); //亮度计算 fixed3 finalColor = renderTexColor.rgb * _Brightness; //饱和度计算 fixed L = dot(finalColor, fixed3(0.2126, 0.7152, 0.0722)); fixed3 LCOlor = (L,L,L); finalColor = lerp(LCOlor, finalColor, _Saturation); //对比度计算 fixed3 avgColor = fixed3(0.5,0.5,0.5); finalColor = lerp(avgColor, finalColor, _Contrast); return fixed4(finalColor.rgb, 1); } ENDCG } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public class BrightnessSaturationContrast : PostEffectBase { [Range(0,5)] public float brightness = 1; [Range(0,5)] public float saturation = 1; [Range(0,5)] public float constrast = 1;
protected override void OnRenderImage(RenderTexture source, RenderTexture destination) { base.OnRenderImage(source, destination); } protected override void UpadateProerty() { if (material != null) { material.SetFloat("_Brightness", brightness); material.SetFloat("_Saturation", brightness); material.SetFloat("_Constrast", brightness); } } }
|