Unity Shader unity文档学习笔记(七):后处理之高斯模糊

比起均值模糊 就是效果要好一点 说性能会好也好不到哪里去
效果
在这里插入图片描述
shader

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unlit/GaussianBlur"
{
    Properties
	{
		_MainTex("Base (RGB)", 2D) = "white" {}
	}
 
	//通过CGINCLUDE我们可以预定义一些下面在Pass中用到的struct以及函数,
	//这样在pass中只需要设置渲染状态以及调用函数,shader更加简洁明了
	CGINCLUDE
	#include "UnityCG.cginc"
 
	//blur结构体,从blur的vert函数传递到frag函数的参数
	struct v2f_blur
	{
		float4 pos : SV_POSITION;	//顶点位置
		float2 uv  : TEXCOORD0;		//纹理坐标
		float4 uv01 : TEXCOORD1;	//一个vector4存储两个纹理坐标
		float4 uv23 : TEXCOORD2;	//一个vector4存储两个纹理坐标
		float4 uv45 : TEXCOORD3;	//一个vector4存储两个纹理坐标
	};
 
	//shader中用到的参数
	sampler2D _MainTex;
	//XX_TexelSize,XX纹理的像素相关大小width,height对应纹理的分辨率,x = 1/width, y = 1/height, z = width, w = height
	float4 _MainTex_TexelSize;
	//给一个offset,这个offset可以在外面设置,是我们设置横向和竖向blur的关键参数
	float4 _offsets;
 
	//vertex shader
	v2f_blur vert_blur(appdata_img v)
	{
		v2f_blur o;
		o.pos = UnityObjectToClipPos(v.vertex);
		//uv坐标
		o.uv = v.texcoord.xy;
 
		//计算一个偏移值,offset可能是(0,1,0,0)也可能是(1,0,0,0)这样就表示了横向或者竖向取像素周围的点
		_offsets *= _MainTex_TexelSize.xyxy;
		
		//由于uv可以存储4个值,所以一个uv保存两个vector坐标,_offsets.xyxy * float4(1,1,-1,-1)可能表示(0,1,0-1),表示像素上下两个
		//坐标,也可能是(1,0,-1,0),表示像素左右两个像素点的坐标,下面*2.0,*3.0同理
		o.uv01 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1);
		o.uv23 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 2.0;
		o.uv45 = v.texcoord.xyxy + _offsets.xyxy * float4(1, 1, -1, -1) * 3.0;
 
		return o;
	}
 
	//fragment shader
	fixed4 frag_blur(v2f_blur i) : SV_Target
	{
		fixed4 color = fixed4(0,0,0,0);
		//将像素本身以及像素左右(或者上下,取决于vertex shader传进来的uv坐标)像素值的加权平均
		color += 0.4 * tex2D(_MainTex, i.uv);
		color += 0.15 * tex2D(_MainTex, i.uv01.xy);
		color += 0.15 * tex2D(_MainTex, i.uv01.zw);
		color += 0.10 * tex2D(_MainTex, i.uv23.xy);
		color += 0.10 * tex2D(_MainTex, i.uv23.zw);
		color += 0.05 * tex2D(_MainTex, i.uv45.xy);
		color += 0.05 * tex2D(_MainTex, i.uv45.zw);
		return color;
	}
 
	ENDCG
 
	//开始SubShader
	SubShader
	{
		//开始一个Pass
		Pass
		{
			//后处理效果一般都是这几个状态
			ZTest Always
			Cull Off
			ZWrite Off
			Fog{ Mode Off }
 
			//使用上面定义的vertex和fragment shader
			CGPROGRAM
			#pragma vertex vert_blur
			#pragma fragment frag_blur
			ENDCG
		}
 
	}
//后处理效果一般不给fallback,如果不支持,不显示后处理即可
}


C#处理

using UnityEngine;
using System.Collections;
 
//编辑状态下也运行
[ExecuteInEditMode]
//继承自PostEffectBase
public class GaussianBlur : PostEffectBase
{
    //模糊半径
    public float BlurRadius = 1.0f;
    //降分辨率
    public int downSample = 2;
    //迭代次数
    public int iteration = 1;
 
    void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (_Material)
        {
            //申请RenderTexture,RT的分辨率按照downSample降低
            RenderTexture rt1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
            RenderTexture rt2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
 
            //直接将原图拷贝到降分辨率的RT上
            Graphics.Blit(source, rt1);
 
            //进行迭代高斯模糊
            for(int i = 0; i < iteration; i++)
            {
                //第一次高斯模糊,设置offsets,竖向模糊
                _Material.SetVector("_offsets", new Vector4(0, BlurRadius, 0, 0));
                Graphics.Blit(rt1, rt2, _Material);
                //第二次高斯模糊,设置offsets,横向模糊
                _Material.SetVector("_offsets", new Vector4(BlurRadius, 0, 0, 0));
                Graphics.Blit(rt2, rt1, _Material);
            }
 
            //将结果输出
            Graphics.Blit(rt1, destination);
 
            //释放申请的两块RenderBuffer内容
            RenderTexture.ReleaseTemporary(rt1);
            RenderTexture.ReleaseTemporary(rt2);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值