Shader-TexturePanner源码的简单梳理

作为一个刚学习shader的菜鸟,当看到TexturePanner这样的组合式的shader,让人眼前一亮,忍不住有一种想探究它的好奇心,想了解一下内部是怎么实现的,顺便学学大佬的思路,所有今天就简单的梳理一下源码,先贴一下shader源码(删除了一部分无用的注释):

// Made with Amplify Shader Editor
// Available at the Unity Asset Store - http://u3d.as/y3X 
Shader "AdultLink/TexturePanner"
{
	Properties
	{
		[NoScaleOffset]_Tex("Tex", 2D) = "white" {}
		[NoScaleOffset]_Masktexture("Mask texture", 2D) = "white" {}
		_Tiling("Tiling", Vector) = (1,1,0,0)
		_Offset("Offset", Vector) = (0,0,0,0)
		[HDR]_Color("Color", Color) = (0,0,0,0)
		[KeywordEnum(Original,Hueshift,Multiply,Replace)] _Colormode("Color mode", Float) = 2
		[Toggle]_Globalemissionflicker("Global emission flicker", Float) = 0
		_Globalemissionflickeramplitude("Global emission flicker amplitude", Float) = 0.5
		_Globalemissionflickerfreq("Global emission flicker freq", Float) = 1
		_Globalemissionflickeroffset("Global emission flicker offset", Float) = 1
		[Toggle]_ScanlinesY("Scanlines Y", Float) = 0
		[Toggle]_ScanlinesZ("Scanlines Z", Float) = 0
		[Toggle]_ScanlinesX("Scanlines X", Float) = 0
		_ScanlinesscaleZ("Scanlines scale Z", Float) = 30
		_ScanlinesscaleX("Scanlines scale X", Float) = 30
		_ScanlinesscaleY("Scanlines scale Y", Float) = 30
		_ScanlinesspeedX("Scanlines speed X", Float) = -5
		_ScanlinesspeedY("Scanlines speed Y", Float) = -5
		_ScanlinesspeedZ("Scanlines speed Z", Float) = -5
		[Toggle]_SharpY("SharpY", Float) = 1
		[Toggle]_SharpZ("SharpZ", Float) = 1
		[Toggle]_SharpX("SharpX", Float) = 1
		_ScrollingspeedX("Scrolling speed X", Float) = -1
		_ScrollingspeedY("Scrolling speed Y", Float) = 0
		[Toggle]_Horizontalstretch("Horizontalstretch", Float) = 0
		[Toggle]_Verticalstretch("Vertical stretch", Float) = 0
		_Horizontalstretchamplitude("Horizontal stretch amplitude", Range( 0 , 1)) = 0.5
		_Verticalstretchamplitude("Vertical stretch amplitude", Range( 0 , 1)) = 0.5
		_Horizontalstretchfreq("Horizontal stretch freq", Float) = 0.5
		_Verticalstretchfreq("Vertical stretch freq", Float) = 0.5
		_Horizontalstretchoffset("Horizontal stretch offset", Float) = 0
		_Verticalstretchoffset("Vertical stretch offset", Float) = 0
		_Verticalstretchpivotpoint("Vertical stretch pivot point", Range( -1 , 1)) = -0.06438866
		_Horizontalstretchpivotpoint("Horizontal stretch pivot point", Range( -1 , 1)) = 0
		[Toggle]_Horizontalmovement("Horizontalmovement", Float) = 0
		[Toggle]_Verticalmovement("Vertical movement", Float) = 0
		_Horizontalmovementamplitude("Horizontal movement amplitude", Float) = 0.5
		_Verticalmovementamplitude("Vertical movement amplitude", Float) = 0.5
		_Horizontalmovementfreq("Horizontal movement freq", Float) = 1
		_Verticalmovementfreq("Vertical movement freq", Float) = 1
		_Horizontalmovementoffset("Horizontal movement offset", Float) = 0
		_Verticalmovementoffset("Vertical movement offset", Float) = 0
		_RotationSpeed("Rotation Speed", Float) = 1
		_Masktexturerotationspeed("Mask texture rotation speed", Float) = 0
		[KeywordEnum(Scroll,Rotate,None)] _Scrollrotate("Scroll rotate", Float) = 0
		_Masktexturetiling("Mask texture tiling", Vector) = (1,1,0,0)
		_Masktextureoffset("Mask texture offset", Vector) = (0,0,0,0)
		[HideInInspector] _texcoord( "", 2D ) = "white" {}
		[HideInInspector] __dirty( "", Int ) = 1
	}

	SubShader
	{
		Tags{ "RenderType" = "Transparent"  "Queue" = "Transparent+0" "IgnoreProjector" = "True" "IsEmissive" = "true"  }
		Cull Off
		CGPROGRAM
		#include "UnityShaderVariables.cginc"
		#pragma target 3.0
		#pragma shader_feature _COLORMODE_ORIGINAL _COLORMODE_HUESHIFT _COLORMODE_MULTIPLY _COLORMODE_REPLACE
		#pragma shader_feature _SCROLLROTATE_SCROLL _SCROLLROTATE_ROTATE _SCROLLROTATE_NONE
		#pragma surface surf Standard alpha:fade keepalpha noshadow vertex:vertexDataFunc 
		struct Input
		{
			float2 uv_texcoord;
			float3 worldPos;
		};

		uniform float _Horizontalmovement;
		uniform float _Horizontalmovementfreq;
		uniform float _Horizontalmovementamplitude;
		uniform float _Horizontalmovementoffset;
		uniform float _Horizontalstretch;
		uniform float _Horizontalstretchfreq;
		uniform float _Horizontalstretchamplitude;
		uniform float _Horizontalstretchoffset;
		uniform float _Horizontalstretchpivotpoint;
		uniform float _Verticalmovement;
		uniform float _Verticalmovementfreq;
		uniform float _Verticalmovementamplitude;
		uniform float _Verticalmovementoffset;
		uniform float _Verticalstretch;
		uniform float _Verticalstretchfreq;
		uniform float _Verticalstretchamplitude;
		uniform float _Verticalstretchoffset;
		uniform float _Verticalstretchpivotpoint;
		uniform float _Globalemissionflicker;
		uniform float _Globalemissionflickerfreq;
		uniform float _Globalemissionflickeramplitude;
		uniform float _Globalemissionflickeroffset;
		uniform float _ScanlinesX;
		uniform float _SharpX;
		uniform float _ScanlinesscaleX;
		uniform float _ScanlinesspeedX;
		uniform float _ScanlinesY;
		uniform float _SharpY;
		uniform float _ScanlinesscaleY;
		uniform float _ScanlinesspeedY;
		uniform float _ScanlinesZ;
		uniform float _SharpZ;
		uniform float _ScanlinesscaleZ;
		uniform float _ScanlinesspeedZ;
		uniform sampler2D _Tex;
		uniform float _ScrollingspeedX;
		uniform float _ScrollingspeedY;
		uniform float2 _Tiling;
		uniform float2 _Offset;
		uniform float _RotationSpeed;
		uniform float4 _Color;
		uniform sampler2D _Masktexture;
		uniform float2 _Masktexturetiling;
		uniform float2 _Masktextureoffset;
		uniform float _Masktexturerotationspeed;

		float3 HSVToRGB( float3 c )
		{
			float4 K = float4( 1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0 );
			float3 p = abs( frac( c.xxx + K.xyz ) * 6.0 - K.www );
			return c.z * lerp( K.xxx, saturate( p - K.xxx ), c.y );
		}

		float3 RGBToHSV(float3 c)
		{
			float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
			float4 p = lerp( float4( c.bg, K.wz ), float4( c.gb, K.xy ), step( c.b, c.g ) );
			float4 q = lerp( float4( p.xyw, c.r ), float4( c.r, p.yzx ), step( p.x, c.r ) );
			float d = q.x - min( q.w, q.y );
			float e = 1.0e-10;
			return float3( abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
		}

		void vertexDataFunc( inout appdata_full v, out Input o )
		{
			UNITY_INITIALIZE_OUTPUT( Input, o );
			float mulTime201 = _Time.y * _Horizontalmovementfreq;
			float HorizontalMovement212 = lerp(0.0,(sin( mulTime201 )*_Horizontalmovementamplitude + _Horizontalmovementoffset),_Horizontalmovement);
			float mulTime190 = _Time.y * _Horizontalstretchfreq;
			float3 ase_vertex3Pos = v.vertex.xyz;
			float3 Vertexpos163 = ase_vertex3Pos;
			float HorizontalStretch217 = lerp(0.0,( (sin( mulTime190 )*_Horizontalstretchamplitude + _Horizontalstretchoffset) * ( _Horizontalstretchpivotpoint + Vertexpos163.x ) ),_Horizontalstretch);
			float mulTime111 = _Time.y * _Verticalmovementfreq;
			float VerticalMovement210 = lerp(0.0,(sin( mulTime111 )*_Verticalmovementamplitude + _Verticalmovementoffset),_Verticalmovement);	
			float mulTime91 = _Time.y * _Verticalstretchfreq;
			float VerticalStretch215 = lerp(0.0,( (sin( mulTime91 )*_Verticalstretchamplitude + _Verticalstretchoffset) * ( _Verticalstretchpivotpoint + Vertexpos163.y ) ),_Verticalstretch);
			float4 appendResult86 = (float4(( HorizontalMovement212 + HorizontalStretch217 ) , ( VerticalMovement210 + VerticalStretch215 ) , 0.0 , 0.0));
			v.vertex.xyz += appendResult86.xyz;
		}

		void surf( Input i , inout SurfaceOutputStandard o )
		{
			float mulTime99 = _Time.y * _Globalemissionflickerfreq;
			float EmissionFlicker228 = lerp(1.0,(pow( sin( mulTime99 ) , 2.0 )*(0.0 + (_Globalemissionflickeramplitude - 0.0) * (0.1 - 0.0) / (1.0 - 0.0)) + _Globalemissionflickeroffset),_Globalemissionflicker);
			float mulTime147 = _Time.y * _ScanlinesspeedX;
			float clampResult150 = clamp( sin( (i.uv_texcoord.x*_ScanlinesscaleX + mulTime147) ) , 0.0 , 1.0 );
			float ScanlinesX220 = lerp(1.0,lerp(clampResult150,ceil( clampResult150 ),_SharpX),_ScanlinesX);
			float mulTime26 = _Time.y * _ScanlinesspeedY;
			float clampResult175 = clamp( sin( (i.uv_texcoord.y*_ScanlinesscaleY + mulTime26) ) , 0.0 , 1.0 );
			float ScanlinesY222 = lerp(1.0,lerp(clampResult175,ceil( clampResult175 ),_SharpY),_ScanlinesY);
			float3 ase_vertex3Pos = mul( unity_WorldToObject, float4( i.worldPos , 1 ) );
			float mulTime154 = _Time.y * _ScanlinesspeedZ;
			float clampResult157 = clamp( sin( (ase_vertex3Pos.z*_ScanlinesscaleZ + mulTime154) ) , 0.0 , 1.0 );
			float ScanlinesZ224 = lerp(1.0,lerp(clampResult157,ceil( clampResult157 ),_SharpZ),_ScanlinesZ);
			float2 appendResult70 = (float2(_ScrollingspeedX , _ScrollingspeedY));
			float2 temp_output_80_0 = (float2( 0,0 ) + (_Offset - float2( 0,0 )) * (float2( 1,1 ) - float2( 0,0 )) / (float2( 360,360 ) - float2( 0,0 )));
			float2 uv_TexCoord7 = i.uv_texcoord * _Tiling + temp_output_80_0;
			float2 panner4 = ( _Time.y * appendResult70 + uv_TexCoord7);
			float2 uv_TexCoord185 = i.uv_texcoord * _Tiling + temp_output_80_0;
			float mulTime181 = _Time.y * _RotationSpeed;
			float cos179 = cos( mulTime181 );
			float sin179 = sin( mulTime181 );
			float2 rotator179 = mul( uv_TexCoord185 - ( _Tiling * float2( 0.5,0.5 ) ) , float2x2( cos179 , -sin179 , sin179 , cos179 )) + ( _Tiling * float2( 0.5,0.5 ) );
			#if defined(_SCROLLROTATE_SCROLL)
				float2 staticSwitch187 = panner4;
			#elif defined(_SCROLLROTATE_ROTATE)
				float2 staticSwitch187 = rotator179;
			#elif defined(_SCROLLROTATE_NONE)
				float2 staticSwitch187 = uv_TexCoord7;
			#else
				float2 staticSwitch187 = panner4;
			#endif
			float4 PannedRotatedTexture231 = tex2D( _Tex, staticSwitch187 );
			float4 CombinedTexture41 = ( EmissionFlicker228 * ScanlinesX220 * ScanlinesY222 * ScanlinesZ224 * PannedRotatedTexture231 );
			float3 hsvTorgb125 = RGBToHSV( CombinedTexture41.rgb );
			float3 hsvTorgb126 = RGBToHSV( _Color.rgb );
			float3 hsvTorgb127 = HSVToRGB( float3(( hsvTorgb125.x + hsvTorgb126.x ),hsvTorgb125.y,hsvTorgb125.z) );
			float2 uv_TexCoord238 = i.uv_texcoord * _Masktexturetiling + _Masktextureoffset;
			float mulTime247 = _Time.y * _Masktexturerotationspeed;
			float cos248 = cos( mulTime247 );
			float sin248 = sin( mulTime247 );
			float2 rotator248 = mul( uv_TexCoord238 - ( _Masktexturetiling * float2( 0.5,0.5 ) ) , float2x2( cos248 , -sin248 , sin248 , cos248 )) + ( _Masktexturetiling * float2( 0.5,0.5 ) );
			float Masktexture241 = tex2D( _Masktexture, rotator248 ).a;
			float CombinedTexture_alpha51 = ( CombinedTexture41.a * Masktexture241 );
			#if defined(_COLORMODE_ORIGINAL)
				float4 staticSwitch40 = CombinedTexture41;
			#elif defined(_COLORMODE_HUESHIFT)
				float4 staticSwitch40 = float4( hsvTorgb127 , 0.0 );
			#elif defined(_COLORMODE_MULTIPLY)
				float4 staticSwitch40 = ( CombinedTexture41 * _Color );
			#elif defined(_COLORMODE_REPLACE)
				float4 staticSwitch40 = ( _Color * CombinedTexture_alpha51 );
			#else
				float4 staticSwitch40 = ( CombinedTexture41 * _Color );
			#endif
			float4 FinalEmission234 = staticSwitch40;
			o.Emission = FinalEmission234.rgb;
			o.Alpha = CombinedTexture_alpha51;
		}

		ENDCG
	}
	CustomEditor "TexturePannerEditor"
}

很明显这是一个表面着色器,所以麻烦了,自己本身对表面着色器只有一点点了解,毕竟大部分时间都去学习顶点、片元着色器了,没办法硬着头皮看吧。

#pragma surface surf Standard alpha:fade keepalpha noshadow vertex:vertexDataFunc 
  • 定义宏:
#pragma shader_feature _COLORMODE_ORIGINAL _COLORMODE_HUESHIFT _COLORMODE_MULTIPLY _COLORMODE_REPLACE
#pragma shader_feature _SCROLLROTATE_SCROLL _SCROLLROTATE_ROTATE _SCROLLROTATE_NONE
  • 看一下自定义的两个函数吧:
float3 HSVToRGB( float3 c )
{
    float4 K = float4( 1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0 );
    float3 p = abs( frac( c.xxx + K.xyz ) * 6.0 - K.www );
    return c.z * lerp( K.xxx, saturate( p - K.xxx ), c.y );
}

float3 RGBToHSV(float3 c)
{
    float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    float4 p = lerp( float4( c.bg, K.wz ), float4( c.gb, K.xy ), step( c.b, c.g ) );
    float4 q = lerp( float4( p.xyw, c.r ), float4( c.r, p.yzx ), step( p.x, c.r ));
    float d = q.x - min( q.w, q.y );
    float e = 1.0e-10;
    return float3( abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

嗯……看不懂,看函数名知道干啥的,内部代码不知道干啥的(要不这篇博客就到这吧)。目测(只是目测),没记错的话,学shader的时候大佬的博客说这段代码好像出自shadertoy,我菜鸟一个也不清楚。

不管了我们接着往下看:

  • 顶点函数:
void vertexDataFunc( inout appdata_full v, out Input o )
{
    UNITY_INITIALIZE_OUTPUT( Input, o );
    float mulTime201 = _Time.y * _Horizontalmovementfreq;
    float HorizontalMovement212 = lerp(0.0,(sin( mulTime201 )*_Horizontalmovementamplitude + _Horizontalmovementoffset),_Horizontalmovement);
    float mulTime190 = _Time.y * _Horizontalstretchfreq;
    float3 ase_vertex3Pos = v.vertex.xyz;
    float3 Vertexpos163 = ase_vertex3Pos;
    float HorizontalStretch217 = lerp(0.0,( (sin( mulTime190 )*_Horizontalstretchamplitude + _Horizontalstretchoffset) * ( _Horizontalstretchpivotpoint + Vertexpos163.x ) ),_Horizontalstretch);
    float mulTime111 = _Time.y * _Verticalmovementfreq;
    float VerticalMovement210 = lerp(0.0,(sin( mulTime111 )*_Verticalmovementamplitude + _Verticalmovementoffset),_Verticalmovement);	
    float mulTime91 = _Time.y * _Verticalstretchfreq;
    float VerticalStretch215 = lerp(0.0,( (sin( mulTime91 )*_Verticalstretchamplitude + _Verticalstretchoffset) * ( _Verticalstretchpivotpoint + Vertexpos163.y ) ),_Verticalstretch);
    float4 appendResult86 = (float4(( HorizontalMovement212 + HorizontalStretch217 ) , (     VerticalMovement210 + VerticalStretch215 ) , 0.0 , 0.0));
    v.vertex.xyz += appendResult86.xyz;
}
  • 初始化Input变量
UNITY_INITIALIZE_OUTPUT( Input, o );

中间插一下,讲一下别的东西(一个简单的公式):

y = Asin(ωx + φ) + k

这是一个正弦函数(当然不是标准的),重点不在这里,如果足够细心,你会发现作者通篇应用了这个函数,在这个函数中

振幅: A(Amplitude)
频率:ω / 2π(Frequency)
初相:φ(PrimaryPhase)
偏移:k(Offset)

这也意味着作者的大部分效果是一个具有固定周期的往复运动,通过这些参数让我们更好的调整效果,所以,显而易见:

  • 顶点水平位移:
float mulTime201 = _Time.y * _Horizontalmovementfreq;
float HorizontalMovement212 = lerp(0.0,(sin( mulTime201 )*_Horizontalmovementamplitude + _Horizontalmovementoffset),_Horizontalmovement);
  • 顶点水平拉伸:
float mulTime190 = _Time.y * _Horizontalstretchfreq;
float HorizontalStretch217 = lerp(0.0,( (sin( mulTime190 )*_Horizontalstretchamplitude + _Horizontalstretchoffset) * ( _Horizontalstretchpivotpoint + Vertexpos163.x ) ),_Horizontalstretch);		

其中和顶点水平位移不同的是,在sin函数处理完之后和锚点的偏移参数相乘,达到了顶点拉伸的效果;

  • 顶点垂直位移:
float mulTime111 = _Time.y * _Verticalmovementfreq;
float VerticalMovement210 = lerp(0.0,(sin( mulTime111 )*_Verticalmovementamplitude + _Verticalmovementoffset),_Verticalmovement);
  • 顶点垂直拉伸(对锚点的处理和水平相同):
float mulTime91 = _Time.y * _Verticalstretchfreq;
float VerticalStretch215 = lerp(0.0,( (sin( mulTime91 )*_Verticalstretchamplitude + _Verticalstretchoffset) * ( _Verticalstretchpivotpoint + Vertexpos163.y ) ),_Verticalstretch);
  • 最后合并结果并返回:
float4 appendResult86 = (float4(( HorizontalMovement212 + HorizontalStretch217 ) , ( VerticalMovement210 + VerticalStretch215 ) , 0.0 , 0.0));
v.vertex.xyz += appendResult86.xyz;

在顶点函数中,这两段重复代码:

float3 ase_vertex3Pos = v.vertex.xyz;
float3 Vertexpos163 = ase_vertex3Pos;

作者定义了两个相同的变量,却只有Vertexpos163被使用,我并不认为是作者故意的;在作者的GitHub主页上作者说是通过Amplify Shader Editor实现的,没用过(ASE???类似于shader Graph的可编程插件),猜测是在连连看时为了布局好看(也许),生成了多余的变量。

  • 表面函数:
void surf( Input i , inout SurfaceOutputStandard o )
{
    float mulTime99 = _Time.y * _Globalemissionflickerfreq;
    float EmissionFlicker228 = lerp(1.0,(pow( sin( mulTime99 ) , 2.0 )*(0.0 + (_Globalemissionflickeramplitude - 0.0) * (0.1 - 0.0) / (1.0 - 0.0)) + _Globalemissionflickeroffset),_Globalemissionflicker);
    float mulTime147 = _Time.y * _ScanlinesspeedX;
    float clampResult150 = clamp( sin( (i.uv_texcoord.x*_ScanlinesscaleX + mulTime147) ) , 0.0 , 1.0 );
    float ScanlinesX220 = lerp(1.0,lerp(clampResult150,ceil( clampResult150 ),_SharpX),_ScanlinesX);
    float mulTime26 = _Time.y * _ScanlinesspeedY;
    float clampResult175 = clamp( sin( (i.uv_texcoord.y*_ScanlinesscaleY + mulTime26) ) , 0.0 , 1.0 );
    float ScanlinesY222 = lerp(1.0,lerp(clampResult175,ceil( clampResult175 ),_SharpY),_ScanlinesY);
    float3 ase_vertex3Pos = mul( unity_WorldToObject, float4( i.worldPos , 1 ) );
    float mulTime154 = _Time.y * _ScanlinesspeedZ;
    float clampResult157 = clamp( sin( (ase_vertex3Pos.z*_ScanlinesscaleZ + mulTime154) ) , 0.0 , 1.0 );
    float ScanlinesZ224 = lerp(1.0,lerp(clampResult157,ceil( clampResult157 ),_SharpZ),_ScanlinesZ);
    float2 appendResult70 = (float2(_ScrollingspeedX , _ScrollingspeedY));
    float2 temp_output_80_0 = (float2( 0,0 ) + (_Offset - float2( 0,0 )) * (float2( 1,1 ) - float2( 0,0 )) / (float2( 360,360 ) - float2( 0,0 )));
    float2 uv_TexCoord7 = i.uv_texcoord * _Tiling + temp_output_80_0;
    float2 panner4 = ( _Time.y * appendResult70 + uv_TexCoord7);
    float2 uv_TexCoord185 = i.uv_texcoord * _Tiling + temp_output_80_0;
    float mulTime181 = _Time.y * _RotationSpeed;
    float cos179 = cos( mulTime181 );
    float sin179 = sin( mulTime181 );
    float2 rotator179 = mul( uv_TexCoord185 - ( _Tiling * float2( 0.5,0.5 ) ) , float2x2( cos179 , -sin179 , sin179 , cos179 )) + ( _Tiling * float2( 0.5,0.5 ) );
    #if defined(_SCROLLROTATE_SCROLL)
        float2 staticSwitch187 = panner4;
    #elif defined(_SCROLLROTATE_ROTATE)
        float2 staticSwitch187 = rotator179;
    #elif defined(_SCROLLROTATE_NONE)
        float2 staticSwitch187 = uv_TexCoord7;
    #else
        float2 staticSwitch187 = panner4;
    #endif
    float4 PannedRotatedTexture231 = tex2D( _Tex, staticSwitch187 );
    float4 CombinedTexture41 = ( EmissionFlicker228 * ScanlinesX220 * ScanlinesY222 * ScanlinesZ224 * PannedRotatedTexture231 );
    float3 hsvTorgb125 = RGBToHSV( CombinedTexture41.rgb );
    float3 hsvTorgb126 = RGBToHSV( _Color.rgb );
    float3 hsvTorgb127 = HSVToRGB( float3(( hsvTorgb125.x + hsvTorgb126.x ),hsvTorgb125.y,hsvTorgb125.z) );
    float2 uv_TexCoord238 = i.uv_texcoord * _Masktexturetiling + _Masktextureoffset;
    float mulTime247 = _Time.y * _Masktexturerotationspeed;
    float cos248 = cos( mulTime247 );
    float sin248 = sin( mulTime247 );
    float2 rotator248 = mul( uv_TexCoord238 - ( _Masktexturetiling * float2( 0.5,0.5 ) ) , float2x2( cos248 , -sin248 , sin248 , cos248 )) + ( _Masktexturetiling * float2( 0.5,0.5 ) );
    float Masktexture241 = tex2D( _Masktexture, rotator248 ).a;
    float CombinedTexture_alpha51 = ( CombinedTexture41.a * Masktexture241 );
    #if defined(_COLORMODE_ORIGINAL)
        float4 staticSwitch40 = CombinedTexture41;
    #elif defined(_COLORMODE_HUESHIFT)
        float4 staticSwitch40 = float4( hsvTorgb127 , 0.0 );
    #elif defined(_COLORMODE_MULTIPLY)
        float4 staticSwitch40 = ( CombinedTexture41 * _Color );
    #elif defined(_COLORMODE_REPLACE)
        float4 staticSwitch40 = ( _Color * CombinedTexture_alpha51 );
    #else
        float4 staticSwitch40 = ( CombinedTexture41 * _Color );
    #endif
    float4 FinalEmission234 = staticSwitch40;
    o.Emission = FinalEmission234.rgb;
    o.Alpha = CombinedTexture_alpha51;
}
  • 在表面函数里作者先处理的是自发光:
float mulTime99 = _Time.y * _Globalemissionflickerfreq;
float EmissionFlicker228 = lerp(1.0,(pow( sin( mulTime99 ) , 2.0 )*(0.0 + (_Globalemissionflickeramplitude - 0.0) * (0.1 - 0.0) / (1.0 - 0.0)) + _Globalemissionflickeroffset),_Globalemissionflicker);	

在这里作者首先对原始sin函数进行了pow(平方),让我不明白的是作者为什么做一些无意义的运算:加0、减0,除以1……如果有知道的朋友拿饭告诉我一声,在此感谢;

  • x轴扫描线:
float mulTime147 = _Time.y * _ScanlinesspeedX;
float clampResult150 = clamp( sin( (i.uv_texcoord.x*_ScanlinesscaleX + mulTime147) ) , 0.0 , 1.0 );
float ScanlinesX220 = lerp(1.0,lerp(clampResult150,ceil( clampResult150 ),_SharpX),_ScanlinesX);

在这里作者对sin函数的结果进行了clamp(截断),限制在了0和1之间,由于sin函数的值域为-1到1,所有在sin函数的一个完整周期内会有一半的数据为0,另一半数据为0到1,在图像上表现为一半黑一半渐变为白色,作者在后边的代码中对这个数据相乘来实现在x轴上把画面切割的效果,其他两个轴的是相同的原理;同时在第三行代码中作者通过ceil函数对数据向上取整,来保证数据统一,实际就是通过了_SharpX这个参数控制clampResult150是否从0渐变为1还是全为1,在视觉效果上就是渐变强度或整体统一强度;

  • y轴扫描线:
float mulTime26 = _Time.y * _ScanlinesspeedY;
float clampResult175 = clamp( sin( (i.uv_texcoord.y*_ScanlinesscaleY + mulTime26) ) , 0.0 , 1.0 );
float ScanlinesY222 = lerp(1.0,lerp(clampResult175,ceil( clampResult175 ),_SharpY),_ScanlinesY);
  • z轴扫描线:
float3 ase_vertex3Pos = mul( unity_WorldToObject, float4( i.worldPos , 1 ) );
float mulTime154 = _Time.y * _ScanlinesspeedZ;
float clampResult157 = clamp( sin( (ase_vertex3Pos.z*_ScanlinesscaleZ + mulTime154) ) , 0.0 , 1.0 );
float ScanlinesZ224 = lerp(1.0,lerp(clampResult157,ceil( clampResult157 ),_SharpZ),_ScanlinesZ);

z轴和x轴和y轴不同,x轴和y轴操作的是uv,z轴操作的是深度,在实际效果上有点诡异(自己试一下就知道了),并没有看到作者使用z轴进行扫描;

  • uv滚动:
float2 appendResult70 = (float2(_ScrollingspeedX , _ScrollingspeedY));
float2 temp_output_80_0 = (float2( 0,0 ) + (_Offset - float2( 0,0 )) * (float2( 1,1 ) - float2( 0,0 )) / (float2( 360,360 ) - float2( 0,0 )));
float2 uv_TexCoord7 = i.uv_texcoord * _Tiling + temp_output_80_0;
float2 panner4 = ( _Time.y * appendResult70 + uv_TexCoord7);
float2 uv_TexCoord185 = i.uv_texcoord * _Tiling + temp_output_80_0;

在temp_output_80_0这个变量上,原谅我并没有看懂,尤其是那个360;

  • uv旋转:
float mulTime181 = _Time.y * _RotationSpeed;
float cos179 = cos( mulTime181 );
float sin179 = sin( mulTime181 );
float2 rotator179 = mul( uv_TexCoord185 - ( _Tiling * float2( 0.5,0.5 ) ) , float2x2( cos179 , -sin179 , sin179 , cos179 )) + ( _Tiling * float2( 0.5,0.5 ) );

偏移至中心,通过旋转矩阵进行uv旋转;

  • 通过宏处理滚动/旋转
#if defined(_SCROLLROTATE_SCROLL)
    float2 staticSwitch187 = panner4;
#elif defined(_SCROLLROTATE_ROTATE)
    float2 staticSwitch187 = rotator179;
#elif defined(_SCROLLROTATE_NONE)
    float2 staticSwitch187 = uv_TexCoord7;
#else
    float2 staticSwitch187 = panner4;
#endif
  • 合并主贴图计算结果:
float4 PannedRotatedTexture231 = tex2D( _Tex, staticSwitch187 );
float4 CombinedTexture41 = ( EmissionFlicker228 * ScanlinesX220 * ScanlinesY222 * ScanlinesZ224 * PannedRotatedTexture231 );

合并自发光、扫描线;

  • 计算Hueshift(Colormode):
float3 hsvTorgb125 = RGBToHSV( CombinedTexture41.rgb );
float3 hsvTorgb126 = RGBToHSV( _Color.rgb );
float3 hsvTorgb127 = HSVToRGB( float3(( hsvTorgb125.x + hsvTorgb126.x ),hsvTorgb125.y,hsvTorgb125.z) );
  • 通过宏控制颜色混合模式:
#if defined(_COLORMODE_ORIGINAL)
    float4 staticSwitch40 = CombinedTexture41;
#elif defined(_COLORMODE_HUESHIFT)
    float4 staticSwitch40 = float4( hsvTorgb127 , 0.0 );
#elif defined(_COLORMODE_MULTIPLY)
    float4 staticSwitch40 = ( CombinedTexture41 * _Color );
#elif defined(_COLORMODE_REPLACE)
    float4 staticSwitch40 = ( _Color * CombinedTexture_alpha51 );
#else
    float4 staticSwitch40 = ( CombinedTexture41 * _Color );
#endif
  • 输出最终颜色和Alpha:
float4 FinalEmission234 = staticSwitch40;
o.Emission = FinalEmission234.rgb;
o.Alpha = CombinedTexture_alpha51;
  • 最后还有一个自定义面板:
CustomEditor "TexturePannerEditor"

通篇读下来,感觉就是把一堆单独的效果组装到了一起;不过有一点无论某个模块的功能你用还是不用,代码都会运算一遍,感觉做了很多无用功,可能大概还需要优化吧!

  • 补充一点toggle的用法:
toggle:0或1
floatx value = lerp(0,计算的值,toggle);

其实,还是想分析一下TexturePannerEditor的,但是在写这篇博客的过程中被打断了3次,搞得一点脾气都没有!好吧,就这样吧!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值