【Unity】管道流动模拟Shader
抽象模拟管道介质流动的效果,使用顶点片元着色器。可以调整管线光泽,颜色,流动方向,透明度,流动体粗细,流动速度和横断面。
实现效果
Demo效果
管线光泽调整
管线颜色调整
流动方向调整
透明度调整
流动体粗细调整
管线横断
流动速度调整
shader源码
c#
Shader "Unlit/PipeShaderTwoPass"
{
Properties
{
_MoveTex("MoveTexture", 2D) = "white" {}
_PipeTex("PipeTexture", 2D) = "white" {}
_Color("Color",Color) = (1,1,1,0)
[HDR]_MoveColor("MoveColor",Color) = (1,1,1,0)
_CutVector("CutVector",Vector) = (0, 1, 0, 0)
_CutCenter("CutCenter",Vector) = (0, 1, 0, 0)
[Enum(Off,0,On,1)]_isCut("isCut",int) = 1
[Enum(Off,0,On,1)]_isFront("isFront",int) = 1
[Enum(Off,0,On,1)]_isMove("isMove",int) = 1
_Alpha("Alpha",Range(0.85, 1.0)) = 1
_Speed("Speed",Range(1, 3)) = 0.1
_Metallic("Metallic", Range(0.0, 1.0)) = 0.5
_Smoothness("Smoothness", Range(1.0, 2.0)) = 0.5
_R("R",Range(0,1)) = 1
}
SubShader
{
Pass
{
Tags { "RenderType" = "Opaque" }
LOD 100
ZWrite On
Cull Off //关闭剔除
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MoveTex;
float4 _MoveTex_ST;
float4 _CutCenter;
float4 _CutVector;
float4 _MoveColor;
int _isCut;
int _isFront;
int _isMove;
float _Speed;
float _R;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD1;
};
v2f vert(appdata v)
{
v2f o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.vertex = UnityObjectToClipPos(v.vertex - (v.normal * _R));
o.uv = TRANSFORM_TEX(v.uv, _MoveTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float2 uv = i.uv;
if (_isFront)
{
uv = float2(i.uv.x, -i.uv.y);
}
fixed4 col = tex2D(_MoveTex, uv - float2(0, _isMove * _Speed * _Time.y));
if (_isCut == 1)
{
float3 cutVector = normalize(_CutVector.xyz);//切割向量
float3 targetVer = i.worldPos - _CutCenter;//切割原点到模型点上的向量
float angel = -dot(cutVector, normalize(targetVer));//切割向量和targetVer点乘,正则同方向,父则反方向
clip(angel);//反方向剔除
}
clip(col.x - 0.1);
return col* _MoveColor;
}
ENDCG
}
Pass
{
Tags { "RenderType" = "Opaque" "IgnoreProjector" = "True" "Queue" = "Geometry" }
LOD 100
ZWrite On
Cull Off //关闭剔除
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityLightingCommon.cginc" // 对于 _LightColor0
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
float3 worldPos : TEXCOORD1;
half3 worldNormal : TEXCOORD2;
fixed4 diff : COLOR0; // 漫射光照颜色
};
sampler2D _PipeTex;
float4 _PipeTex_ST;
float4 _CutCenter;
float4 _CutVector;
int _isCut;
fixed _Verical;
float _Alpha;
float4 _Color;
float _Metallic;
float _Smoothness;
v2f vert(appdata v)
{
v2f o;
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _PipeTex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
half nl = max(0, dot(o.worldNormal, _WorldSpaceLightPos0.xyz) * 0.5 + 0.5);
o.diff = nl * _LightColor0;
o.diff.rgb += ShadeSH9(half4(o.worldNormal, 1));
return o;
}
fixed4 frag(v2f i) : SV_Target
{
float2 uv = i.uv;
fixed4 col = tex2D(_PipeTex, uv);
if (_isCut == 1)
{
float3 cutVector = normalize(_CutVector.xyz);//切割向量
float3 targetVer = i.worldPos - _CutCenter;//切割原点到模型点上的向量
float angel = -dot(cutVector, normalize(targetVer));//切割向量和targetVer点乘,正则同方向,父则反方向
clip(angel);//反方向剔除
}
// 计算视图方向和反射矢量
// 此处为每像素计算
half3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
half3 worldRefl = reflect(-worldViewDir, i.worldNormal);
// 与在先前的着色器中相同
half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldRefl);
half3 skyColor = DecodeHDR(skyData, unity_SpecCube0_HDR);
fixed4 c = 0;
c.rgb = skyColor * _Metallic;
half4 endColor;
endColor = fixed4(((_Color + c) * i.diff * _Smoothness).rgb, _Color.a);
return fixed4(endColor.rgb, _Alpha);
}
ENDCG
}
}
}