屏幕后处理——亮度饱和度对比度、边缘检测

一、亮度、饱和度、对比度

脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
//在编辑器下也可执行
[ExecuteInEditMode]
public class BrightnessShader : MonoBehaviour
{
    public Shader Brightshader;

    private Material mat;

    //亮度
    public float Brightness;

    //饱和度
    public float Saturation;

    //对比度
    public float Contrast;

    public Material Mat
    {
        get
        {
            if(mat==null)
            {
                Material _newmat = new Material(Brightshader);
                _newmat.hideFlags= HideFlags.HideAndDontSave;
                mat = _newmat;
                return mat;
            }
            else
            {
                return mat;
            }
        }
    }

    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        Mat.SetFloat("_Brightness", Brightness);
        Mat.SetFloat("_Saturation", Saturation);
        Mat.SetFloat("_Contrast", Contrast);
        Graphics.Blit(src, dest, Mat);
    }
}

Shader:

Shader"unity/BrightShader"
{
	Properties
	{
		_MainTex("MainTex",2D)="white"{}
		//亮度调节
		_Brightness("Brightness",float)=1.0
		//饱和度调节
		_Saturation("Saturation",float)=1.0
		//对比度调节
		_Contrast("Contrast",float)=1.0
	 }

	SubShader
	{
		Pass
		{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			float _Saturation;
			float _Brightness;
			float _Contrast;

			struct appdate
			{
				float4 vertex : POSITION;
				float4 uv : TEXCOORD;
			 };

			struct v2f
			{
				float4 pos : SV_POSITION;
				float4 uv : TEXCOORD;
			 };

			v2f vert(appdate v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				o.uv=v.uv;
				return o;
			 }

			float4 frag(v2f i):SV_Target
			{
				float4 mainTex = tex2D(_MainTex,i.uv);
				//亮度颜色
				float3 finalColor = mainTex.rgb*_Brightness;

				//饱和度

				//计算该像素的亮度值
				float luminance = 0.2125*mainTex.r+0.7154*mainTex.g+0.0721*mainTex.b;
				//饱和度为0的颜色值
				float3 luminanceColor=float3(luminance,luminance,luminance);
				//插值
				finalColor=lerp(luminanceColor,finalColor,_Saturation);

				//对比度
				//对比度为0的颜色值
				float3 avgColor=float3(0.5,0.5,0.5);
				finalColor=lerp(avgColor,finalColor,_Contrast);

				return float4(finalColor,mainTex.a);
			 }

			ENDCG
		 }
	 }
 }

 

二、边缘检测

 脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class EdgeDetection : MonoBehaviour
{
    public Shader EdgeShader;

    [Range(0,1)]public float WO;

    private Material mat;

    public Material Mat
    {
        get
        {
            if(mat==null)
            {
                Material _newmat = new Material(EdgeShader);
                _newmat.hideFlags = HideFlags.HideAndDontSave;
                mat = _newmat;
                return mat;
            }
            else
            {
                return mat;
            }
        }
    }
    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        Mat.SetColor("_EdgeColor", Color.black);
        Mat.SetColor("_BackgroundColor", Color.white);
        Mat.SetFloat("_EdgeWithOnly", WO);
        Graphics.Blit(src,dest,Mat);
    }
}

Shader:

Shader"unity/EdgeShader"
{
	Properties
	{
		_MainTex("MainTex",2D)="white"{}
		//滑杆
		_EdgeWithOnly("EdgeWithOnly",float)=0
		//描边颜色
		_EdgeColor("EdgeColor",Color)=(0,0,0,0)
		//背景颜色
		_BackgroundColor("BackgroundColor",Color)=(0,0,0,0)
	 }

	SubShader
	{
		Pass
		{
			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			//纹理中对应每个像素的大小;例如512*512的纹理,其值为1/512
			float4 _MainTex_TexelSize;
			//描边颜色
			float4 _EdgeColor;
			//背景颜色
			float4 _BackgroundColor;
			//背景颜色调节滑杆
			float _EdgeWithOnly;

			struct appdate 
			{
				float4 vertex : POSITION;
				float4 uv : TEXCOORD;
			 };

			struct v2f 
			{
				float4 pos : SV_POSITION;
				//定义了某像素的纹理坐标以及其邻域的8个纹理坐标
				float2 uv[9] : TEXCOORD;
			 };

			v2f vert(appdate v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				o.uv[0]=v.uv+_MainTex_TexelSize*float2(-1,-1);
				o.uv[1]=v.uv+_MainTex_TexelSize*float2(0,-1);
				o.uv[2]=v.uv+_MainTex_TexelSize*float2(1,-1);
				o.uv[3]=v.uv+_MainTex_TexelSize*float2(-1,0);
				o.uv[4]=v.uv+_MainTex_TexelSize*float2(0,0);
				o.uv[5]=v.uv+_MainTex_TexelSize*float2(1,0);
				o.uv[6]=v.uv+_MainTex_TexelSize*float2(-1,1);
				o.uv[7]=v.uv+_MainTex_TexelSize*float2(0,1);
				o.uv[8]=v.uv+_MainTex_TexelSize*float2(1,1);
				return o;
			 }

			 // 在线性颜色空间下的RGB 转为灰度值的心理学公式
			fixed luminance(fixed4 color)
    		{
    			return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
    		}

		    // 应用Sobel卷积
		    half Sobel(v2f i)
    		{
				const half Gx[9] = {-1,  0,  1,
										-2,  0,  2,
										-1,  0,  1};
				const half Gy[9] = {-1, -2, -1,
										0,  0,  0,
										1,  2,  1};		
				
    			half texColor;
    			half GradientX = 0;
    			half GradientY  = 0;
    			for (int index = 0;index<9;index++)
    			{
    				texColor = luminance(tex2D(_MainTex,i.uv[index]));
    				GradientX += texColor * Gx[index];
    				GradientY += texColor * Gy[index];
    			}
    			half edge = 1-abs(GradientX)-abs(GradientY);

    			return edge;    //edge越小 表明该像素越可能是边缘
    		}

			float4 frag(v2f i):SV_Target
			{
				//Sobel函数利用Sobel算子对原图进行边缘检测
				float edge = Sobel(i);
				//既有原图也有边缘的颜色
				float4 withEdgeColor=lerp(_EdgeColor,tex2D(_MainTex,i.uv[4]),edge);
				//只有边缘和纯色的颜色
				float4 OnlyEdgeColor=lerp(_EdgeColor,_BackgroundColor,edge);
				//前两者的混合
				return lerp(withEdgeColor,OnlyEdgeColor,_EdgeWithOnly);
			 }

			ENDCG
		 }
	 }
 }

三、效果展示

【太妃糖耶】更新啦,赶紧来围观吧!

详细知识解析见书 P246 

猜你喜欢

转载自blog.csdn.net/2401_83878847/article/details/146831240
今日推荐