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"
}

写完~ 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Unity Shader Graph是Unity引擎中的一种可视化编程工具,它可以用于创建自定义的着色器效果。溶解特效是一种常见的特效,在游戏和动画中经常使用。 要使用Unity Shader Graph实现溶解特效,我们需要做以下几个步骤: 1. 创建Shader Graph:打开Unity编辑器,创建一个新的Shader Graph。可以通过右键点击Assets面板中的空白区域,选择Create->Shader->PBR Graph来创建一个新的Shader Graph。 2. 添加输入节点:在Shader Graph编辑器中,我们需要添加溶解特效所需的输入节点。这些节点可能包括Texture2D用于溶解图案、Float用于控制溶解的进度等。 3. 控制溶解过程:在Shader Graph中,我们可以使用节点连接和编辑来控制溶解特效的过程。例如,我们可以使用Lerp节点将溶解图案与原始纹理进行混合,实现溶解的效果。 4. 添加溶解动画:通过使用Time节点,我们可以在Shader Graph中添加时间变量,以使溶解过程可以动态进行,从而实现溶解特效的动画效果。通过控制Time节点的输入值,我们可以控制溶解特效的速度、方向等。 5. 调整其他属性:除了溶解图案和动画外,还可以通过Shader Graph调整其他属性,如颜色、透明度、光照等,以使溶解特效具有更多的变化和个性化。 6. 导入及应用Shader:将编写好的Shader Graph保存,然后将其导入Unity项目中。之后,我们可以将其应用到需要溶解特效的材质上,以实现溶解特效效果。 总之,通过使用Unity Shader Graph,我们可以通过可视化编辑界面来快速创建和调整溶解特效。这种方法非常直观和灵活,使得艺术家和开发人员可以快速实现他们想要的效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值