【Unity3d Shader】高斯模糊效果

高斯模糊可以实现模糊效果,可用于眩晕,场景动画等效果

高斯模糊利用了卷积计算,把每个像素和周围的像素混合

见代码实现

c#代码 ImageEffectBase

using UnityEngine;

namespace GameBase.Effect
{
    [RequireComponent(typeof (Camera))]
    [AddComponentMenu("")]
    public class ImageEffectBase : MonoBehaviour
    {
        /// Provides a shader property that is set in the inspector
        /// and a material instantiated from the shader
        public Shader shader;

        private Material m_Material;


        protected virtual void Start()
        {
            // Disable if we don't support image effects
            if (!SystemInfo.supportsImageEffects)
            {
                enabled = false;
                return;
            }

            // Disable the image effect if the shader can't
            // run on the users graphics card
            if (!shader || !shader.isSupported)
                enabled = false;
        }


        protected Material material
        {
            get
            {
                if (m_Material == null)
                {
                    m_Material = new Material(shader);
                    m_Material.hideFlags = HideFlags.HideAndDontSave;
                }
                return m_Material;
            }
        }


        protected virtual void OnDisable()
        {
            if (m_Material)
            {
                DestroyImmediate(m_Material);
            }
        }
    }
}

c#代码 BlurEffect

using UnityEngine;

namespace GameBase.Effect
{
    public class BlurEffect : ImageEffectBase
    {

        [Range(0, 10)]
        [SerializeField]
        private int _downSample = 1;//分辨率降低值

        [SerializeField]
        [Range(0, 8)]
        private float _blurSize = 1;//取周围多远的像素

        [SerializeField]
        [Range(1, 10)]
        private int _filterCount = 1;//滤波次数(越大性能越差)

        private int ID_BlurSize;

        private void OnEnable()
        {
            ID_BlurSize = Shader.PropertyToID("_BlurSize");
        }

        void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            if(_blurSize <= 0 )
            {
                Graphics.Blit(source, destination);
                return;
            }
            int width = source.width >> _downSample;
            int height = source.height >> _downSample;
            if (width <= 0)
                width = 1;
            if (height <= 0)
                height = 1;

            if (_filterCount == 1)
            {
                RenderTexture bufferRT = RenderTexture.GetTemporary(width, height, 0, source.format);
                if (material.HasProperty(ID_BlurSize))
                {
                    material.SetFloat(ID_BlurSize, _blurSize);
                }
                Graphics.Blit(source, bufferRT, material, 0);
                Graphics.Blit(bufferRT, destination, material, 1);
                RenderTexture.ReleaseTemporary(bufferRT);
            }
            else
            {
                RenderTexture bufferRT1 = RenderTexture.GetTemporary(width, height, 0, source.format);
                RenderTexture bufferRT2 = RenderTexture.GetTemporary(width, height, 0, source.format);
               
                if (material.HasProperty(ID_BlurSize))
                {
                    material.SetFloat(ID_BlurSize, _blurSize);
                }
                Graphics.Blit(source, bufferRT1, material, 0);
                for (int i = 1; i < _filterCount; i++)
                {
                    Graphics.Blit(bufferRT1, bufferRT2, material, 1);
                    Graphics.Blit(bufferRT2, bufferRT1, material, 0);
                }

                Graphics.Blit(bufferRT1, destination, material, 1);

                RenderTexture.ReleaseTemporary(bufferRT1);
                RenderTexture.ReleaseTemporary(bufferRT2);
            }

        }
    }
}

shader代码 

Shader "mgo/blur" 
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_BlurSize("_BlurSize", range(0, 300)) = 1
	}

	SubShader
	{
		Tags{ "RenderType" = "Opaque" }
		
		ZTest Off
		cull Off
		ZWrite Off

		Pass
		{
			Name "Horizontal"
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata {
				float4 vertex:POSITION;
				float2 uv:TEXCOORD0;
			};

			struct v2f
			{
				float4 pos:SV_POSITION;
				float2 uv:TEXCOORD0;
			};

			uniform sampler2D _MainTex;
			//xxx_TexelSize 是用来访问xxx纹理对应的每个文素的大小 ,如一张512*512的图该值大小为1/512≈0.001953125
			uniform float4 _MainTex_TexelSize;
			uniform half _BlurSize;

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

			half4 frag(v2f i) : SV_Target
			{

				float texelSize = _MainTex_TexelSize.x * _BlurSize;
				float2 uv = i.uv;
				half4 c0 = tex2D(_MainTex, uv - float2(texelSize * 4.0, 0.0));
				half4 c1 = tex2D(_MainTex, uv - float2(texelSize * 3.0, 0.0));
				half4 c2 = tex2D(_MainTex, uv - float2(texelSize * 2.0, 0.0));
				half4 c3 = tex2D(_MainTex, uv - float2(texelSize * 1.0, 0.0));
				half4 c4 = tex2D(_MainTex, uv                               );
				half4 c5 = tex2D(_MainTex, uv + float2(texelSize * 1.0, 0.0));
				half4 c6 = tex2D(_MainTex, uv + float2(texelSize * 2.0, 0.0));
				half4 c7 = tex2D(_MainTex, uv + float2(texelSize * 3.0, 0.0));
				half4 c8 = tex2D(_MainTex, uv + float2(texelSize * 4.0, 0.0));
				half4 color = c0 * 0.01621622 + c1 * 0.05405405 + c2 * 0.12162162 + c3 * 0.19459459
							+ c4 * 0.22702703
							+ c5 * 0.19459459 + c6 * 0.12162162 + c7 * 0.05405405 + c8 * 0.01621622;
				return color;
			}
			ENDCG
		}

		Pass
		{
			Name "Vertical"
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata {
				float4 vertex:POSITION;
				float2 uv:TEXCOORD0;
			};

			struct v2f
			{
				float4 pos:SV_POSITION;
				float2 uv:TEXCOORD0;
			};

			uniform sampler2D _MainTex;
			uniform float4 _MainTex_TexelSize;
			uniform half _BlurSize;

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

			fixed4 frag(v2f i) : SV_Target
			{
				float texelSize = _MainTex_TexelSize.y * _BlurSize;
				float2 uv = i.uv;

				half4 c0 = tex2D(_MainTex, uv - float2(0.0, texelSize * 4.0));
				half4 c1 = tex2D(_MainTex, uv - float2(0.0, texelSize * 3.0));
				half4 c2 = tex2D(_MainTex, uv - float2(0.0, texelSize * 2.0));
				half4 c3 = tex2D(_MainTex, uv - float2(0.0, texelSize * 1.0));
				half4 c4 = tex2D(_MainTex, uv                               );
				half4 c5 = tex2D(_MainTex, uv + float2(0.0, texelSize * 1.0));
				half4 c6 = tex2D(_MainTex, uv + float2(0.0, texelSize * 2.0));
				half4 c7 = tex2D(_MainTex, uv + float2(0.0, texelSize * 3.0));
				half4 c8 = tex2D(_MainTex, uv + float2(0.0, texelSize * 4.0));
				half4 color = c0 * 0.01621622 + c1 * 0.05405405 + c2 * 0.12162162 + c3 * 0.19459459
							+ c4 * 0.22702703
							+ c5 * 0.19459459 + c6 * 0.12162162 + c7 * 0.05405405 + c8 * 0.01621622;
				return color;

			}
			ENDCG
		}

		
	}
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要实现图像扭曲过场效果,可以使用Unity3D中的Shader。具体实现步骤如下: 1. 创建一个新的Shader,并将其属性设置为Unlit/Texture。 2. 在Shader中添加一个名为“Distortion”的属性,类型为2D纹理,用于存储扭曲图像。 3. 在Shader中添加一个名为“DistortionStrength”的属性,类型为Range,用于控制扭曲强度。 4. 在Shader的片段着色器中,使用tex2D函数获取原始纹理的颜色,并使用uv坐标对扭曲图像进行采样。 5. 将扭曲图像的采样值与“DistortionStrength”属性相乘,并将结果添加到原始颜色中。 6. 最后,将新的颜色值输出到屏幕。 下面是一个简单的Shader示例: ``` Shader "Custom/DistortionTransition" { Properties { _MainTex ("Texture", 2D) = "white" {} _Distortion ("Distortion", 2D) = "white" {} _DistortionStrength ("Distortion Strength", Range(0.0, 1.0)) = 0.5 } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _MainTex; sampler2D _Distortion; float _DistortionStrength; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { // Get the original color fixed4 texColor = tex2D(_MainTex, i.uv); // Get the distortion value float4 distortion = tex2D(_Distortion, i.uv); // Calculate the distortion offset float2 offset = (distortion.rg * 2.0 - 1.0) * _DistortionStrength; // Apply the distortion to the UV coordinates float2 distortedUV = i.uv + offset; // Get the color from the distorted UV coordinates fixed4 distortedColor = tex2D(_MainTex, distortedUV); // Add the distortion to the original color return texColor + (distortedColor - texColor); } ENDCG } } FallBack "Diffuse" } ``` 在使用这个Shader时,可以将原始纹理作为“_MainTex”属性的值,将扭曲图像作为“_Distortion”属性的值,然后通过修改“_DistortionStrength”属性的值来控制扭曲强度。 希望这个示例能够帮助你实现所需的效果

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值