简易MotionBlur效果实现学习以及疑惑若干——UnityShader学习笔记复习

博主分享了在C#和Shader中实现运动模糊效果的过程,质疑乐乐女神的复杂操作是否必要。通过实验发现,一个Pass和简化操作即可达成效果,寻求理解和指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


自言自语

这次回家继续复习白天学习的乐乐女神的 简易motionblur效果实现。 很简单 代码很快就码完了。但没效果。。。 检查shader没问题 又检查C# 发现几句代码的顺序错了 造成没有报错 但是没效果。于是按照逻辑理了一下顺序 效果呈现。

但是本着好奇的心 又按照自己的理解 过了一遍代码 发现。。。不按照乐乐女神的写法 只要一个pass 也不用进行ColorMask 操作 以及C#中的 *RenderTexture.MarkRestoreExpected();*操作也一样能实现相同的效果,就很不明白 为什么乐乐女神要做这么多操作。。。

可能还是没真正理解原理。 求各位大佬指教 如果这篇笔记有幸被大佬们看到的话

效果

在这里插入图片描述
在这里插入图片描述

实现步骤及疑惑都写在代码注释里了

C#部分

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


[ExecuteInEditMode]
public class MotionBlurWang : PostProcessWangBase
{
    [Range(0f, 0.9f)]
    public float BlurFactor = 0f;

    public Shader motionShader;
    private Material motionMaterial = null;
    public Material Omaterial
    {
        get
        {
            motionMaterial = CheckShaderAndMaterial(motionShader, motionMaterial);
            return motionMaterial;
        }
    }

    private RenderTexture motionTex = null;
    //不运行的时候 就销毁这个图 免得重影..
    private void OnDisable()
    {
        DestroyImmediate(motionTex);
    }

    protected void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if(Omaterial == null )
        {
            Graphics.Blit(source, destination);
        }
        else
        {
            //这里边执行顺序不能乱  之前写的乱了没有出现效果
            //判断如果没有 或者 尺寸不对  则执行销毁 并重新给他一个现在的图源
            if (motionTex == null || motionTex.width != source.width || motionTex.height != source.height)
            {
                DestroyImmediate(motionTex);
                motionTex = new RenderTexture(source.width, source.height, 0);
                //手动销毁 无需出现在面板和场景中 不随场景保存
                motionTex.hideFlags = HideFlags.HideAndDontSave;
                //初始化完成后把现在的图源给 motion图
                Graphics.Blit(source, motionTex);
            }
            //如果都本身就有符合条件的motion图则直接进行 恢复操作  
            //其实没明白为啥要做这一步..因为我注释掉这一步 效果也是正常的...
            //有知道的大佬请指导下
            motionTex.MarkRestoreExpected();
            //设置好需要融合的也就是shader中的Alpha值 进行一个取反 使数值从小到大的变化对应 模糊效果的从弱到强 
            Omaterial.SetFloat("_MotionBlur", 1.0f - BlurFactor);
            //利用shader的混合把新图源处理后叠加在motion上 处理叠加都在shader中进行
            Graphics.Blit(source, motionTex, Omaterial);
            //然后把处理好的图 渲染到目标图像上 完成!@
            Graphics.Blit(motionTex, destination);
        }

    }
}

Shader部分

Shader "TNShaderPractise/ShaderPractise_MotionBlur"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque"  "Queue" ="Transparent" }
		//两个Pass 要公用一个顶点着色器 所以就直接还是CGINCLUDE的起步
		CGINCLUDE
		sampler2D _MainTex;
		//模糊强度  就是叠加图层的alpha值
		float _MotionBlur;

		struct a2v
		{
			float4 vertex : POSITION;
			float4 texcoord : TEXCOORD0;
		};		

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

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

			return o;
		}
		//叠加的模糊图 也就是画好的 虚掉的第一张图 可以理解为上一张图,其 Alpha值用参数控制,代表虚化程度,Alpha值越大则虚化越小 模糊效果越大
		//由于C#中进行了OneMinus操作 所以则C#面板上 数值越大 则Alpha越小 则虚化越大,模糊效果越大
		fixed4 fragRGB (v2f i) : SV_Target
		{
			fixed4 motionTex = fixed4 (tex2D (_MainTex,i.uv).rgb,_MotionBlur);

			return motionTex;
		}
	   //理解为现在正在呈现的这张图 其Alpah为其本身状态 
		fixed4 fragA (v2f i) : SV_Target
		{
		//此pass只是把现在这在渲染的图渲染出来且保留其自身Alpha
			fixed4 motionTex = tex2D (_MainTex,i.uv);

			return motionTex;
		}
		ENDCG

		ZWrite Off ZTest Always Cull Off

		//pass 0 进行虚化效果渲染
		Pass
		{
			//由于要混合两个pass 所以开启blend 且基于alpha混合 blend模式设置为透明度混合 
			Blend SrcAlpha OneMinusSrcAlpha
			//这里 用 ColorMask 只写入RGB的通道信息 
			//经过测试 不按乐乐女神写法 直接全通道写入也是一样的效果 因为这里的A通道已经被我们参数设置好了值 所以可以和下边的全图进行混合了
			//ColorMask rgb
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment fragRGB
			ENDCG
		}

		//Pass
		//{
		//	//这个pass需要渲染出现在图像的Alpha值 保证现在图像叠加上一张虚化的图像
		//	//所以混合模式为实打实的混合
		//	//经测试 这个PASS混合模式可以不开启。。。 也一样的效果。。为啥要专门开启一下没明白
		//	//Blend One Zero
		//	//但写入的通道只是Alpha通道  两个Pass合一起 就是理解为 前一张图 我只写入RGB通道 A通道是自定义的所以等于全部写入一个虚影 来和  下一张图的Alpha 混合一下 
		//	//呈现的效果叠加效果就是 当前图的实心加上上一张图的剩下的一点虚影边界
		//	ColorMask A
		//	但是当我尝试进行不写入通道操作的时候...也能生效. 所以什么都不写入 就靠一个空Pass叠加 也能有用? 那我是不是不用多一个pass?
		//	//ColorMask 0
		//	CGPROGRAM
		//	#pragma vertex vert
		//	#pragma fragment fragA
		//	ENDCG
		//}

		//事实证明...真的一个pass就够用了..  为啥要写俩??? 好难受..
        
    }
		FallBack Off
}

总结

不能理解乐乐女神为什么要写更多的操作来实现这个简易的motionblur效果。本来照着他的思路来 貌似已经接近理解的边缘了。但随着自己的理解更加深入我心,我尝试做了修改 去掉了我认为不必要的代码,竟然也能实现同样的效果我就不是很懂了。。。 还求有缘人能给我指点一二啊。。乐乐女神这么做总归是有原因的吧。学习的内容还是太少。所以自己不敢做判断 只能是简单尝试。 哎 。继续学习吧。

这两天有点懈怠了。。 进度慢了下来。。 要鞭策下自己了。看在牛年到来之前能把这第一本书啃完不!加油吧 艰难爬行的 我

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值