Loading

# shader——无限循环背景的制作

制作前准备

  1. 需求要求
    • UI中的一张图片需要无限制的斜向移动。
  2. 图片设置准备

开始制作

首先我们需要一个mainTexture的参数和调节速度的参数,所以我们在Properties块中定义2个属性,代码如下:

	Properties {
		_MainTex ("Main Texture", 2D) = "black" {}
		_speed ("speed", Range(0, 10)) = 0.5
	}

然后我们设立一个结构体v2f来存储转换位置后的数据,代码如下:

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

其中:
float4 pos : SV_POSITION 表示转换后的顶点位置,half2 uvTA: TEXCOORD0 表示转换后的顶点纹理坐标。

接着我们开始具体的转换,代码如下:

		v2f vert(appdata_img v) {
			v2f o;
			o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
			o.uvTA = v.texcoord;
			return o;
		}

其中,appdata_img v 表示输入的顶点数据,包含了顶点的位置和纹理坐标等信息。v.vertex 表示顶点的位置,v.texcoord 表示顶点的纹理坐标。

mul(UNITY_MATRIX_MVP, v.vertex) 表示将顶点的位置乘以当前的模型视图投影矩阵(MVP 矩阵)进行转换,得到转换后的顶点位置。

最后,将转换后的顶点位置和纹理坐标打包成一个 v2f 结构体,并返回转换后的数据,进行uv偏移的操作,代码如下:

fixed4 frag(v2f i) : SV_Target {
			float2 uv = i.uvTA;
			uv.x -= _Time.y * _speed;
			uv.y -= _Time.y * _speed;
            if (uv.x > 1.0 || uv.y > 1.0) {
                uv.x -= 1.0;
            	uv.y -= 1.0;
            }
            if (uv.x < 0.0 || uv.y < 0.0) {
                uv.x += 1.0;
            	uv.y += 1.0;
            }
			return tex2D(_MainTex, uv).rgba ;
		}

如果,背景图需要结合Mask遮罩的话,需要在Properties段加入以下代码:

Properties {
		...
		
		_StencilComp("Stencil Comparison", Float) = 8
		_Stencil("Stencil ID", Float) = 0
		_StencilOp("Stencil Operation", Float) = 0
		_StencilWriteMask("Stencil Write Mask", Float) = 255
		_StencilReadMask("Stencil Read Mask", Float) = 255
		_ColorMask("Color Mask", Float) = 15
	}
	

再在Pass段中加入以下代码:

	Pass {
			//加入下面一段
            Stencil
            {
                Ref[_Stencil]
                Comp[_StencilComp]
                Pass[_StencilOp]
                ReadMask[_StencilReadMask]
                WriteMask[_StencilWriteMask]
            }
            ColorMask[_ColorMask]
			
			...
		}

最后实现的效果

因为是UI所以需要挂在画布下

效果Gif如下:

shader全部代码:

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

Shader "TUT/BackgroundLoop_P1" {
	Properties {
		_MainTex ("Main Texture", 2D) = "black" {}
		_speed ("speed", Range(0, 10)) = 0.5
		
		
		_StencilComp("Stencil Comparison", Float) = 8
		_Stencil("Stencil ID", Float) = 0
		_StencilOp("Stencil Operation", Float) = 0
		_StencilWriteMask("Stencil Write Mask", Float) = 255
		_StencilReadMask("Stencil Read Mask", Float) = 255
		_ColorMask("Color Mask", Float) = 15
	}
	SubShader {
		Tags {"Queue"="Transparent" }
		CGINCLUDE

		#include "UnityCG.cginc"

		sampler2D _MainTex;  
		uniform half4 _MainTex_ST;
		
		struct v2f {
			float4 pos : SV_POSITION;
			half2 uvTA: TEXCOORD0;
		};
		
		v2f vert(appdata_img v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			o.uvTA = v.texcoord;
			return o;
		}
		
		float _speed;
		fixed4 frag(v2f i) : SV_Target {
			//第一版本
			//float2 uv = i.uvTA;
			//uv.x -= _Time.y * _speed;
			//uv.y -= _Time.y * _speed;
			//if (uv.x > 1.0 || uv.y > 1.0) {
				//uv.x -= 1.0;
				//uv.y -= 1.0;
			//}
			//if (uv.x < 0.0 || uv.y < 0.0) {
				//uv.x += 1.0;
				//uv.y += 1.0;
			//}
			//return tex2D(_MainTex, uv).rgba ;
			//之后把这里重新修改了一下
			return tex2D(_MainTex, i.uvTA - (_Time.y * _speed)).rgba;
		}
		    
		ENDCG
		Pass {
			
			//加入下面一段
            Stencil
            {
                Ref[_Stencil]
                Comp[_StencilComp]
                Pass[_StencilOp]
                ReadMask[_StencilReadMask]
                WriteMask[_StencilWriteMask]
            }
            ColorMask[_ColorMask]
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			  
			#pragma vertex vert  
			#pragma fragment frag

			ENDCG  
		}
		}
	FallBack "Diffuse"
}

引用:

[Unity+shader]无限循环背景的制作
普通的Shader-给ui写shader后mask失效解决

posted @ 2023-03-03 16:37  数学天才琪露诺  阅读(192)  评论(0编辑  收藏  举报