UnityShader入门精要第十二章(运动模糊效果)

实现运动模糊的方法:累计缓存和速度缓存。

accumulation buffer:物体快速移动产生多张连续图像,取他们平均值作为最后的运动模糊图像。

cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveBlurCS : PostEffectsBase
{
    public Shader motionBlurShader;
    private Material motionBlurMaterial;

    public Material material
    {
        get
        {
            motionBlurMaterial = CheckShaderAndCreateMaterial(motionBlurShader, motionBlurMaterial);
            return motionBlurMaterial;
        }
    }

    [Range(0.0f, 0.9f)]
    public float blurAmount = 0.5f;


    //声明一张纹理存储混合图像
    private RenderTexture accumulationTexture;


    //当脚本不运行时立刻删除该纹理,因为下次调用时会产生新的纹理
    private void OnDisable()
    {
        DestroyImmediate(accumulationTexture);
    }


    
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        //当有这个材质时
        if (material != null)
        {
            //当混合图像不存在或者混合图像高和宽不符合当前图像时,删除并新建一个新的纹理
            if (accumulationTexture == null || accumulationTexture.width != source.width || accumulationTexture.height != source.height)
            {
                DestroyImmediate(accumulationTexture);
                accumulationTexture = new RenderTexture(source.width, source.height, 0);

                //我们自己控制该变量的销毁,所以不显示在Hierarchy中,也不会保存在场景中
                accumulationTexture.hideFlags = HideFlags.HideAndDontSave;

                //将当前帧导入到纹理中
                //Blit 将 accumulationTexture 设置为渲染目标,在材质上设置 source _MainTex 属性, 并绘制全屏四边形
                Graphics.Blit(source, accumulationTexture);
            }


            //混合图像参与混合后又会重新恢复
            accumulationTexture.MarkRestoreExpected();

            //将混合参数传入shader中
            //上一帧的比例为blurAmount
            //这一帧的比例就时1-blurAmount了
            material.SetFloat("_BlurAmount", 1.0f - blurAmount);

            //当前帧进行pass处理,混合进混合图像后,将结果输出进混合图像
            //如果继续进行运动,上一帧就是我们上一帧的混合图像。
            //所以运动越持久,混合越多
            //上上上帧的比例会不断减少
            Graphics.Blit(source, accumulationTexture, material);
            
            //导出混合图像
            Graphics.Blit(accumulationTexture, destination);
        }
        else
        {
            Graphics.Blit(source, destination);
        }   
    }
}

shader:

Shader "Custom/MoveBlurShader"
{
	Properties
	{
		_MainTex("Main Tex",2D) = "white"{}
		_BlurAmount("Blur Amount",Float) = 1.0
	}

	SubShader
	{
		CGINCLUDE

		#include "UnityCG.cginc"

		sampler2D _MainTex;
		fixed _BlurAmount;

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

		v2f vert(appdata_img v)
		{
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			o.uv = v.texcoord;

			return o;
		}

		//RGB就是RGB的值,A通道是_BlurAmount
		//混合时通过A通道混合
		fixed4 fragRGB(v2f i) : SV_Target 
		{
			return fixed4(tex2D(_MainTex,i.uv).rgb,_BlurAmount);
		}

		//事实上只输出透明度Alpha值
		half4 fragA(v2f i) : SV_Target 
		{
			return tex2D(_MainTex, i.uv);
		}

		ENDCG

		ZTest Always Cull Off ZWrite Off 

		Pass
		{
			Blend SrcAlpha OneMinusSrcAlpha
			 对此通道启用仅写入 RGB 通道,这会禁用向 Alpha 通道写入
			ColorMask RGB

			CGPROGRAM

			#pragma vertex vert 
			#pragma fragment fragRGB

			ENDCG


		}


		Pass
		{
			Blend One Zero
			ColorMask A 

			CGPROGRAM

			#pragma vertex vert 
			#pragma fragment fragA 

			ENDCG

		}
	}
	FallBack Off
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值