Shader 能量法球特效

 

RoadLun原創,轉載請聲明

 

               ~~~~~~~~~~~~······ ~~~~~多圖預警~~~~~~~~~~~~~~~~~~~~~~~~~·

 

 

效果:

 

Gif不清楚,先看一張靜態圖

 

 

 

 

噪波律動法球:

 

 

 

 

 

流動法球:

 

 

 

旋轉法球:

 

 

 

實現:

    1.上訴所有效果均爲在片段函數/着色函數中改變UV的映射方式實現,首先需要新建一個球體,接下來的效果將體現在這個球體上

 

 

  

  2.需要一張帶有Alpha通道的半透明貼圖(如下貼圖,右鍵圖片另存爲即可使用,CSDN有2M限制,所以圖片被壓縮過)

 

因爲此圖是PNG格式,將圖片直接拖到球體上即可看到變爲半透明球體:

 

OK看起來沒錯~ 但其實此時自動生成的材質球附着的Shader是一個unity自帶的只讀的Shader,無法進行操作,所以還是按照步驟來吧!

 

 

    3.新建一個Shader(此處我使用頂點/片段着色器,所以新建一個ImageEffectShader或UnlitShader)。要想實現半透明效果,首先開啓透明度混合,設置渲染隊列爲Transparent(半透明),開啓Cull Off

		Blend One ONE
		CULL OFF
		Tags{"Queue"="Transparent"}

 

    4.實現原理:由易到難,先講流動法球(動圖2),此處我用的是頂點/片段着色器,在片段着色器的UV映射階段,使原本的UV映射的X、Y值隨時間增大而增大:

 
sampler2D _MainTex;
float _WaveSpeed;
fixed4 frag (v2f i) : SV_Target
{
	float2 tmpUV=i.uv;
	tmpUV.y+= _WaveSpeed*_Time.y;    //核心步驟
	//tmpUV.x+=_WaveSpeed*_Time.x;    //核心步驟
	fixed4 col = tex2D(_MainTex,tmpUV);
	return col;
}

 

流動效果就是如此簡單,接下來講解旋轉法球,也就是貼圖UV旋轉:UV可以理解成一個二維座標系,長寬可看作X,Y軸,此處我按照(0.5,0.5)爲圓心進行旋轉,所以先將UV貼圖位移(-0.5,-0.5),用矩陣旋轉後再位移(0.5,0.5)。關於矩陣旋轉

 

			sampler2D _MainTex;
			float _Speed;
			fixed4 frag (v2f i) : SV_Target
			{
				float2 tmpUV =i.uv;
			    tmpUV -=float2(0.5,0.5);            //變換旋轉中心
				float2 angle =_Time*_Speed;				//角度隨時間變化而變化
				float2 result =float2(0,0);         //創建一個容器
				result.x =tmpUV.x * cos(angle) -sin(angle)*tmpUV.y;  //公式
				result.y =tmpUV.x * sin(angle) +cos(angle)*tmpUV.y;  //公式
				tmpUV+=float2(0.5,0.5);             //旋轉中心迴歸
				fixed4 col = tex2D(_MainTex, result);
				// just invert the colors
				//col = 1 - col;
				

				return col;
			}

 

如上效果就實現貼圖旋轉功能。接下來是噪波律動法球(動圖1),這個視覺效果就複雜一點了,

仔細看球表面有火苗一般的搖曳:

 

 

 

 

 

這是通過噪聲圖來影響UV映射到某個像素的位置,噪聲圖可以理解爲一個包含很多隨機數的集合,噪聲圖上某個區域(或某個像素)的灰度值就是一個隨機數。通過這個隨機數,影響UV映射到像素上的位置。

噪聲圖:

 

下圖做個比較:

 

 

接下來讓採樣的噪波圖UV隨時間偏移,就有了gif上的效果。片段函數如下:

uniform float _SpeedX;
uniform float _SpeedY;
uniform float _NoiseStrength;
float4 frag(VertexOutput i) : COLOR {

	//光照函數
    i.normalDir = normalize(i.normalDir);
    float3 normalDirection = i.normalDir;
    float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
    float3 lightColor = _LightColor0.rgb;

    float attenuation = LIGHT_ATTENUATION(i);
    float3 attenColor = attenuation * _LightColor0.xyz;

    float NdotL = max(0.0,dot( normalDirection, lightDirection ));	
    float3 directDiffuse = max( 0.0, NdotL) * attenColor;
    float3 indirectDiffuse = float3(0,0,0);
    indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; 
    
	//x,y方向流動
    float2 FlowUV = (i.uv0+float2((_SpeedX*_Time.g),(_Time.g*_SpeedY)));		
    float4 _NoiseMap_var = tex2D(_NoiseMap,TRANSFORM_TEX(FlowUV, _NoiseMap));
	//噪波強度
    float2 NoiseUV = (i.uv0+(float2(_NoiseMap_var.r,_NoiseMap_var.g)*_NoiseStrength));		
    float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(NoiseUV, _MainTex));
    float3 diffuseColor = _MainTex_var.rgb;
    float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;

    float3 finalColor = diffuse;
    fixed4 finalRGBA = fixed4(finalColor,1);
    UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
    return finalRGBA;
            }

 

源碼:下面是三個Shader的源碼:

1.流動法球特效(動圖2)

Shader "Custom/Flow" 
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_WaveSpeed("貼圖移速",float)=3

	}
	SubShader
	{
		Blend One ONE
		CULL OFF
		Tags{"Queue"="Transparent"}

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};


			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};
			//下面是頂點着色器,有四個可控量,控制振幅、波長、頻率、偏移
			float _Frequency;
			float _Attruibte; 
			float _K2;
			float _B2;
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				return o;
			}
			//下面是片段着色器 控制像素的移動
			sampler2D _MainTex;
			float _WaveSpeed;
			fixed4 frag (v2f i) : SV_Target
			{
				float2 tmpUV=i.uv;
				tmpUV.y+= _WaveSpeed*_Time.y;
				//tmpUV.x+=_WaveSpeed*_Time.x;
				fixed4 col = tex2D(_MainTex,tmpUV);
				return col;
			}
			ENDCG
		}
	}
}

 

2.旋轉法球特效(動圖三)

 

Shader "Custom/Rotate" 
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Speed("旋轉速度",Float)=1
		
		
	}
	SubShader
	{
	cull off	
		Blend SrcAlpha One
		Tags{"Queue"="Geometry+2"}
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag 
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

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

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = v.uv;
				return o;
			}
			//像素的矩陣旋轉  
			//思路:
			//1.先將旋轉中心設爲(0.5,0.5)   默認中心爲(0,0)
			//2.套用旋轉公式
			//3.旋轉完畢,中心回到(0,0)
			sampler2D _MainTex;
			float _Speed;
			fixed4 frag (v2f i) : SV_Target
			{
				float2 tmpUV =i.uv;
			    tmpUV -=float2(0.5,0.5);            //變換旋轉中心
				float2 angle =_Time*_Speed;				//角度隨時間變化而變化
				float2 result =float2(0,0);         //創建一個容器
				result.x =tmpUV.x * cos(angle) -sin(angle)*tmpUV.y;  //套公式
				result.y =tmpUV.x * sin(angle) +cos(angle)*tmpUV.y;  //套公式
				tmpUV+=float2(0.5,0.5);             //旋轉中心迴歸
				fixed4 col = tex2D(_MainTex, result);
				// just invert the colors
				//col = 1 - col;
				

				return col;
			}
			ENDCG
		}
	}
}
  // 關於矩陣旋轉的公式: X:  1    0    0    0      (A爲隨時間變化而變化的角度,下同)
  //			     0  cosA -sinA  0
  //			     0  sinA  cosA  0
  //			     0    0    0    1

  //		        Y: cosA  0   sinA  0
  //			     0    1    0    0
  //			   -sinA  0   cosA  0
  //		             0    0    0    1

  //			Z:  cosA -sinA 0    0
  //			    sinA  cosA 0    0
//			     0    0    1    0
//			     0    0    0    1

 

3.噪波律動法球(動圖一)

 

Shader "Custom/NoiseFlow" {
    Properties {
        _MainTex ("主紋理", 2D) = "bump" {}
        _NoiseMap ("噪聲圖", 2D) = "bump" {}
		_SpeedX("x方向速度",float)=0.02
		_SpeedY("y方向速度",float)=0.02
		_NoiseStrength ("噪波強度",float)=0.1
    }
    SubShader {
	Blend One One
	//Blend SrcAlpha  OneMinusSrcAlpha
	Cull Off
        Tags {
            "Queue"="Transparent"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            
            
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles 
            #pragma target 3.0
            uniform float4 _LightColor0;
            uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
            uniform sampler2D _NoiseMap; uniform float4 _NoiseMap_ST;
            struct VertexInput {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                float4 posWorld : TEXCOORD1;
                float3 normalDir : TEXCOORD2;

            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.normalDir = UnityObjectToWorldNormal(v.normal);
                o.posWorld = mul(unity_ObjectToWorld, v.vertex);
                float3 lightColor = _LightColor0.rgb;
                o.pos = UnityObjectToClipPos( v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }

uniform float _SpeedX;
uniform float _SpeedY;
uniform float _NoiseStrength;
float4 frag(VertexOutput i) : COLOR {

	//光照函數
    i.normalDir = normalize(i.normalDir);
    float3 normalDirection = i.normalDir;
    float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
    float3 lightColor = _LightColor0.rgb;

    float attenuation = LIGHT_ATTENUATION(i);
    float3 attenColor = attenuation * _LightColor0.xyz;

    float NdotL = max(0.0,dot( normalDirection, lightDirection ));	
    float3 directDiffuse = max( 0.0, NdotL) * attenColor;
    float3 indirectDiffuse = float3(0,0,0);
    indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; 
    
	//x,y方向流動
    float2 FlowUV = (i.uv0+float2((_SpeedX*_Time.g),(_Time.g*_SpeedY)));		
    float4 _NoiseMap_var = tex2D(_NoiseMap,TRANSFORM_TEX(FlowUV, _NoiseMap));
	//噪波強度
    float2 NoiseUV = (i.uv0+(float2(_NoiseMap_var.r,_NoiseMap_var.g)*_NoiseStrength));		
    float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(NoiseUV, _MainTex));
    float3 diffuseColor = _MainTex_var.rgb;
    float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;

    float3 finalColor = diffuse;
    fixed4 finalRGBA = fixed4(finalColor,1);
    UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
    return finalRGBA;
            }
            ENDCG
        }
       
    }
    FallBack "Diffuse"
}

寫完~ 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章