终于实现出美术同事想要的这个效果了:
下面就来讲述我写这个shader的思路。
首先需要一张魔法阵的底图:
用一个平面(Plane)做模型,将底图贴在模型上:
代码如下:
Shader "Inception-Fx/FlowInsideOut" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Cull Off
Lighting Off
ZWrite Off
Fog { Mode Off }
Blend One One
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
struct appdata_t {
float4 vertex : POSITION;
half2 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : POSITION;
half2 mainTex : TEXCOORD0;
};
v2f vert (appdata_t v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.mainTex = v.texcoord;
return o;
}
fixed4 frag (v2f i) : COLOR
{
fixed4 baseColor = tex2D(_MainTex, i.mainTex);
return baseColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
这是一个非常普通的半透shader。如果对此理解有困难的话,需要先读一读Unity shader的相关文档,补充一下shader的基础知识。不过这里有几点需要提及的是:
Cull Off 关闭裁剪,因为我们需要Plane的背面面向摄像机时,我们也能看到这个流光效果。
Lighting Off 关闭光照。我们不希望这个魔法阵受到光照的影响。
ZWrite Off 像素深度不写入Z缓冲区。一般半透shader都要加上这句,不然离摄像机更远的被Plane挡住的模型可能会直接显示不出来,半透效果也就失去了本身的意义。
Fog { Mode Off } 关闭雾效,不然如果场景开启了雾效,这张图就会变成下面的样子,整个Plane的轮廓都被显示出来了:
Blend One One 为了节省内存,贴图采用了ETC压缩格式,没有alpha通道,所以为了呈现半透的效果,Blend就要用叠加(additive blending)而不是alpha混合(alpha blending)的方式。
接下来就要考虑如何做出流光的效果了。这也是难点。整个shader的复杂度就在这里。
我们可以从Vetex & Fragment Shader的逻辑开始考虑。Vertex & Fragment Shader的流程大体分为两步:第一步是Vertex Shader,也就是上文代码中的vert函数,作用是计算模型上每个顶点的信息——这里包括顶点在屏幕上的投影坐标和uv;第二步是Fragment Shader