这个是项目中用到的一个小效果,主要拆分成三个:线框渲染+菲涅尔+uv流动;
菲涅尔+uv流动网上很多,没啥好说的,线框渲染的关键代码如下:
[maxvertexcount(9)]
void geom(triangle v2g input[3], inout LineStream<g2f> outStream)
{
for (int i = _geomCount; i < 3; i++)
{
g2f o = (g2f)0;
o.vertex = input[i].vertex;
o.uv = input[i].uv;
o.worldNormal = UnityObjectToWorldNormal(input[i].normal);
outStream.Append(o);
}
outStream.RestartStrip();
}
目的是用Geometry Shader的函数,用于将输入的三角形顶点转换为包含额外信息的LineStream。
函数接收一个包含三个三角形顶点的输入数组input,并将转换后的数据输出到LineStream类型的outStream中,说白了就是为了改变顶点结构体的细分;
以下是pass中的处理方法,我加入了uv流动;
Pass
{ Name"Line"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2g
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 normal:NORMAL;
float4 posObj : TEXCOORD2;
};
struct g2f
{
float2 uv:TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldNormal:TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_ST;
half4 _Color;float _geomCount,_Opacity,_YToward,_LineV;
v2g vert (appdata v)
{
v2g o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.normal = v.normal;
o.posObj = v.vertex;
return o;
}
[maxvertexcount(9)]
void geom(triangle v2g input[3], inout LineStream<g2f> outStream)
{
for (int i = _geomCount; i < 3; i++)
{
g2f o = (g2f)0;
o.vertex = input[i].vertex;
o.uv = input[i].uv;
o.worldNormal = UnityObjectToWorldNormal(input[i].normal);
outStream.Append(o);
}
outStream.RestartStrip();
}
half4 frag (g2f i) : SV_Target
{
//half3 worldNormal = normalize(i.worldNormal);
float4 col = _Color;
i.uv = float2(i.uv.x,i.uv.y+_Time.y*_LineV);
half Mask = saturate(tex2D(_MainTex, i.uv));
col.a*=Mask;
col.a*=_Opacity;
//拧出网格来遮罩
//float posObj_y =saturate(sign(i.posObj.y - _YToward));
return col;
}
ENDCG
}
剩下的菲涅尔没啥可说的,公式化的东西,直接复制;
Pass
{ Name"Fresenl"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
float3 normalDir : TEXCOORD1;
float4 worldPos : TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _FresnelPow;
fixed4 _FresnelColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.normalDir = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : COLOR
{
i.normalDir = normalize(i.normalDir);
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
float dotValue = pow(1 - saturate(dot(i.normalDir,viewDir)),_FresnelPow);
fixed4 resultColor = _FresnelColor;
resultColor *=dotValue;
return resultColor;
}
ENDCG
}