Shader中一个容易懂的计时器实现——UnityShader学习笔记


自言自语

好久没有更新笔记了,一是因为时间少,二是因为搬家,三是因为要啃PBR了太难压力大,四是因为懒惰。好吧,我承认,就是懒惰了。于是今天赶紧更新一篇笔记。督促自己进入学习状态。明天开始啃PBR。但愿我能看懂。
今天是在shader中实现一个计时器。功能是到一定时间进行一种操作。 运用到了smoothstep 和lerp 包含了间隔时间,单次播放时间,淡入淡出时间。和两种颜色混合算法。 看代码挺简单。 但是我当时自己研究了快10个小时没研究出来一个满意的淡入淡出的计算办法,后来经大佬指点2分钟。实现了。。。。 既高兴又羞愧啊 太笨了我。好了不废话了 输入正经内容吧。

一、材质面板

这次我稍微对材质面板进行了一点点小小的整理,这样方便我们这样的美术调整参数时看起来清爽下,其实可以又更好的 GUI实现效果,但是太复杂了。。我好懒,没有继续学习 就用Unity内置的用起来挺轻松 排版效果也够了。

在这里插入图片描述

二、动态效果

在这里插入图片描述

三、shader部分

Shader "TNShaderPractise/ShaderPractise_TimeClock"
{
    Properties
    {
		[Header(LerpColor)]
        [HDR]_Color01 ("测试颜色1",COLOR)=(1,1,1,1)
        //[HDR]_Color02 ("测试颜色2",COLOR)=(0,0,0,0)

		//为了方便观察放张纹理
		_TestTex("测试贴图",2D)="white"{}

		[Space(20)][Header(ColorBlendMode)]
		//内设的单选形式的属性面板写法之一
		[Toggle]_IsLerp("是否插值混合",Float) = 0
		//自定义材质面板风格 当然是UNITY内设好的  Space是上下行间距 (10) 表示10个单位  后边 Header 可以理解为分段标题,方便识别  括号内是标题名 只能用英文 中文测试过编译失败
		[Space(20)][Header(TimeSet)]
		_OncePlay("单次播放时长(为0则不进行变换)",Float)=0
		_TimeInvertal("间隔时长(0为不间隔持续循环播放)",Float)=0
		_FadeIn("淡入时长(0为不淡入无渐变)",Float)=0
		_FadeOut("淡出时长(0为不淡出无过度)",Float)=0

    }
    SubShader
    {
		//因为直接新建的是URP工程 因此不用特别写明 Render Pipeline 就是默认的urp管线shader
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
			//由于只是简单的计算 没有光照模型 引入这么一个文件够了  应该
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
			//为了支持SRPBatcher  将参数都声明在CBUFFER块内
			CBUFFER_START(UnityPerMaterial)
			float4 _Color01;
			float4 _Color02;
			//URP下的纹理声明方式 感觉比built in 繁琐了..	  之前写2行就行 代码还少,现在得写3行。。。
			TEXTURE2D (_TestTex);
			SAMPLER(sampler_TestTex);
			float4 _TestTex_ST;
			//URP下的纹理声明方式 感觉比built in 繁琐了..	  之前写2行就行 代码还少,现在得写3行。。。
			float _IsLerp;
			float _OncePlay;
			float _TimeInvertal;
			float _FadeIn;
			float _FadeOut;
			CBUFFER_END

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

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


            v2f vert (a2v v)
            {
                v2f o;
				//尝试用URP 封装好的方法来进行坐标空间转换
                VertexPositionInputs input = GetVertexPositionInputs(v.vertex.xyz);
				o.pos = input.positionCS;
                o.uv = TRANSFORM_TEX(v.texcoord,_TestTex);
                return o;
            }

			//声明一个方法 当做计时器
			float TimeClock (float TimeInvertal,float OncePlay,float FadeIn,float FadeOut )
			{
				////防止为0为负数的Bug
				FadeIn =max(FadeIn,0.001);
				FadeOut =max(FadeOut,0.001);
				//总时长 由间隔时间 播放时间  淡入淡出时间相加而得
				float totalTime = TimeInvertal+OncePlay+FadeIn+FadeOut;
				//Unity内置时间变量除以总时长取余数 用作一轮时间段的循环计时  举例 假如 总时长为5秒 取余操作则为  随着时间每秒变化 0 1 2 3 4 递增
				float playTime = fmod(_Time.y,totalTime);
				//声明最终返回的变量,在片元着色器中可以当做插值使用
				float Clock;
				//当取余时长小于单次播放时间和淡入时间总和时,则表明插值参数为01曲线递增后持续为1   这里用smoothstep一是方便限制到01区间 而是非线性的递增曲线会视觉上看起来更平滑
				
				if (playTime<OncePlay+FadeIn)
				{
					//这里需要注意 虽然长度是	 _OncePlay+_FadeIn	  但我们不能用这个作为最大值,因为这样 如果淡入时间为0 那么smoothstep也会把_OncePlay也算进去 设置淡入时间就不对了  
					Clock = smoothstep(0,FadeIn,playTime);
				}
				//当取余时长大于单次播放时间和淡入时间总和时,则需要参数从10曲线变化,且持续到一轮时间的最后, 所以根据当前时间点和当前时间段的对应时刻做smoothstep的反向操作.这点需要画图理解.也是利用smoothstep函数的特性 很好用
				else
				{
					Clock = smoothstep(OncePlay+FadeIn+FadeOut,OncePlay+FadeIn,playTime);
				}
				//最后返回Clock作为插值 用于片元着色器中
				return Clock;
			}


            float4 frag (v2f i) : SV_Target
            {
				//调用TimeClock方法 取得Clock插值
				float Clock = TimeClock (_TimeInvertal,_OncePlay,_FadeIn,_FadeOut);
				//为了方便观察还是放张纹理吧		同样这也是 URP下的繁琐的采样纹理贴图的写法...	 注意 这里是SAMPLE 不是 SAMPLER....反正我在这里写错很多次。。。坑啊Unity
				float4 col = SAMPLE_TEXTURE2D(_TestTex,sampler_TestTex,i.uv);
				//判断开关状态 决定颜色混合算法
				if (_IsLerp == 1)
				{
				//利用TimeClock依据时间得到的插值参考值 进行颜色插值计算
					return lerp (_Color01,col,Clock);
				}
				else
				{
				    return lerp (_Color01,_Color01+col,Clock);
				}
					
            }
            ENDHLSL
        }
    }
	FallBack "Universal Render Pipeline/Unlit"
}

总结

写完笔记又到凌晨了。祈祷我这么学习,熬夜能有成果。别猝死了。。。。ORZ 没有天赋又笨又懒只能这么可劲儿造自己了 哈哈 其实夜深人静的时候学习 还蛮爽的 我很Enjoy but 明儿还得上班。。。白天又要工作 又困又累。才是要挺住哦。。。 自己嘴碎,吐槽比代码敲的还多。还好没啥人看。哈哈哈哈哈。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值