应功能需求,要做一个透明水箱效果,并包含一个水位线,表示水位高度,找了一些资源整改了一下,接下来,上代码
效果:
shader:
Shader "Unlit/SpecialFX/Liquid"
{
Properties//属性
{
_Tint("Tint", Color) = (1,1,1,1)
_FillAmount("Fill Amount", Range(0,1)) = 0.0
_WobbleX("WobbleX", Range(-1,1)) = 0.0
_WobbleZ("WobbleZ", Range(-1,1)) = 0.0
_TopColor("Top Color", Color) = (1,1,1,1)
_FoamColor("Foam Line Color", Color) = (1,1,1,1)
_Rim("Foam Line Width", Range(0,0.1)) = 0.0
_RimColor("Rim Color", Color) = (1,1,1,1)
_RimPower("Rim Power", Range(0,10)) = 0.0
_CubeColor("CubeColor", color) = (1,1,1,1)
_Width("Width", range(0,0.5)) = 0.1
_Length("Length", range(0.5,1)) = 0.1
_ScaleColor("ScaleColor", color) = (1,1,1,1)
_ScaleWidth("ScaleLine Width", Range(0,0.1)) = 0.0
_ScaleHight("ScaleLine Hight", range(0,1)) = 0.1
}
SubShader//着色器
{
Tags {"Queue" = "Transparent" "DisableBatching" = "True" }
Pass {
Zwrite On//将像素的深度写入深度缓存中
Cull Off // 关闭阴影剔除
AlphaToMask On // transparency
blend srcalpha oneminussrcalpha
//渲染代码在CGPROGRAM和ENDCG之间
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog// make fog work
#include "UnityCG.cginc"//引入Unity内置定义
fixed4 _Tint;
fixed4 _CubeColor;
fixed4 _LineColor;
fixed _Width;
fixed _Length;
float _FillAmount, _WobbleX, _WobbleZ;
float4 _TopColor, _RimColor, _FoamColor, _ScaleColor;
float _Rim, _RimPower, _ScaleWidth, _ScaleHight;
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float3 viewDir : COLOR;
float3 normal : COLOR2;
float fillEdge : TEXCOORD2;
float warningLine : TEXCOORD1;
};
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
float4 RotateAroundYInDegrees(float4 vertex, float degrees) {
float alpha = degrees * UNITY_PI / 180;
float sina, cosa;
sincos(alpha, sina, cosa);
float2x2 m = float2x2(cosa, sina, -sina, cosa);
return float4(vertex.yz , mul(m, vertex.xz)).xzyw;
}
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
UNITY_TRANSFER_FOG(o,o.pos);
//获取世界坐标
float3 worldPos = mul(unity_ObjectToWorld, v.vertex.xyz);
// XY轴晃动
float3 worldPosX = RotateAroundYInDegrees(float4(worldPos,0),360);
// XZ轴晃动
float3 worldPosZ = float3 (worldPosX.y, worldPosX.z, worldPosX.x);
// 结合旋转与worldPos,基于正弦波,脚本控制
float3 worldPosAdjusted = worldPos + (worldPosX * _WobbleX) + (worldPosZ* _WobbleZ);
// 控制液体高度
o.fillEdge = worldPosAdjusted.y + _FillAmount;
o.warningLine = worldPos.y + _ScaleHight;
o.viewDir = normalize(ObjSpaceViewDir(v.vertex));
o.normal = v.normal;
return o;
}
fixed4 frag(v2f i, fixed facing : VFACE) : SV_Target
{
fixed4 col = _Tint;
//边框线 有待优化 理应不应使用if块
if (((i.uv.x < _Width || i.uv.x > 1 - _Width) && (i.uv.y < 1 - _Length || i.uv.y > _Length)) || ((i.uv.y < _Width || i.uv.y > 1 - _Width) && (i.uv.x < 1 - _Length || i.uv.x > _Length)))
{
col += _CubeColor;
}
//液位线
float4 lineHight = step(i.warningLine,0.5) - step(i.warningLine, (0.5 -_ScaleWidth));
float4 lineColored = lineHight * (_ScaleColor*0.9 );
//烟雾效果
UNITY_APPLY_FOG(i.fogCoord, col);
//边缘高光
float dotProduct = 1 - pow(dot(i.normal, i.viewDir), _RimPower);
float4 RimResult = smoothstep(0.5, 1.0, dotProduct);
RimResult *= _RimColor;
// 液体表面
float4 foam = step(i.fillEdge, 0.5) - step(i.fillEdge, (0.5 - _Rim));
float4 foamColored = foam * (_FoamColor * 0.9);
// 液体内部
float4 result = step(i.fillEdge, 0.5) - foam;
float4 resultColored = result * col;
// 液体融合
float4 finalResult = foamColored + col+ lineColored;
finalResult.rgb += RimResult;
// color of backfaces/ top
float4 topColor = _TopColor * (foam + result);
//VFACE returns positive for front facing, negative for backfacing
return facing > 0 ? finalResult : topColor;
}
ENDCG
}
}
}
c#:
using UnityEngine;
namespace DataVisualization
{
public class Wobble : MonoBehaviour
{
Renderer rend;
Vector3 lastPos;
Vector3 velocity;
Vector3 lastRot;
Vector3 angularVelocity;
public float MaxWobble = 0.03f;
public float WobbleSpeed = 1f;
public float Recovery = 1f;
float wobbleAmountY;
float wobbleAmountZ;
float wobbleAmountToAddY;
float wobbleAmountToAddZ;
float pulse;
float time = 0.5f;
// Use this for initialization
void Start()
{
rend = GetComponent();
}
private void Update()
{
time += Time.deltaTime;
// decrease wobble over time
wobbleAmountToAddY = Mathf.Lerp(wobbleAmountToAddY, 0, Time.deltaTime * (Recovery));
wobbleAmountToAddZ = Mathf.Lerp(wobbleAmountToAddZ, 0, Time.deltaTime * (Recovery));
// make a sine wave of the decreasing wobble
pulse = 2 * Mathf.PI * WobbleSpeed;
wobbleAmountY = wobbleAmountToAddY * Mathf.Sin(pulse * time);
wobbleAmountZ = wobbleAmountToAddZ * Mathf.Sin(pulse * time) * 0.1f;
// send it to the shader
rend.material.SetFloat("_WobbleX", wobbleAmountY);
rend.material.SetFloat("_WobbleZ", wobbleAmountZ);
// velocity
angularVelocity = transform.rotation.eulerAngles - lastRot;
if (Input.GetMouseButton(1))
{
// add clamped velocity to wobble
wobbleAmountToAddY += Mathf.Clamp((Input.GetAxis("Mouse X") + (angularVelocity.z * 0.2f)) * MaxWobble, -MaxWobble, MaxWobble);
wobbleAmountToAddZ += Mathf.Clamp((Input.GetAxis("Mouse Y") + (angularVelocity.x * 0.2f)) * MaxWobble, -MaxWobble, MaxWobble);
}
// keep last position
lastRot = transform.rotation.eulerAngles;
}
}
}