# 【Shader练习-血条】
包括了以下练习内容:
- 裁剪圆角矩形。
- 血量少于一定百分比时闪烁。
- 血条使用位图采样纹理。
- 通过C#代码修改材质参数。
该图片用于采样血量颜色。
Shader "Examples/BloodBarAlpha/Shader/Healthbar" {
Properties {
_HP("血量百分比",Range(0.0,1.0)) = 0.5
_BorderSize("边界距离",Range(0.0,0.5)) = 0.1
_Tex("渐变纹理",2D) = "white" {}
}
SubShader {
Tags {
"RenderType"="Transparent"
"ForceNoShadowCasting" = "True" // 不捕获阴影
"IgnoreProjector"= "True" // 忽略投影
}
Pass {
Zwrite Off
Blend SrcAlpha OneMinusSrcAlpha
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
// 当前的显示血量百分比
uniform float _HP;
uniform float _BorderSize;
uniform sampler2D _Tex;
struct VertexInput {
float4 vertex : POSITION;
float4 uv0 : TEXCOORD0;
};
struct VertexOutput {
float4 pos : SV_POSITION;
float4 uv0 : TEXCOORD0;
};
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos( v.vertex );
o.uv0 = v.uv0;
return o;
}
half4 frag(VertexOutput i) : COLOR {
///////////////////////////////////// 圆角部分 /////////////////////////////////////
// 坐标由0~1扩展成0~8
float2 coords = i.uv0;
coords.x *= 8;
// 一条线段,x值是 0.5~7.5之间 y值是 0.5
float2 pointOnLineSeg = float2(clamp(coords.x,0.5,7.5),0.5);
// 使用距离函数,获取当前坐标点与线段之间的距离
// 乘以2 -1 可以让圆角内的值为正数,圆角外的值为负数
float sdf = distance(coords,pointOnLineSeg)*2-1;
// 剪裁负数部分,也就是去掉圆角外的像素
clip(-sdf);
// 边界
float borderSdf = sdf + _BorderSize;
float pd = fwidth(borderSdf);
// 这样处理的边界,显得更加圆滑
// saturate 函数可以把值限制在0~1之间,大于1为1,小于0为0
float borderMask = 1 - saturate(borderSdf / pd);
//////// 血量部分 //////////////////////////
// 显示血量为1,显示空为0
bool b = i.uv0.x < _HP;
// 根据血量百分比采样颜色,健康绿色,危险红色。
half4 bloodColor = tex2D(_Tex,float2(_HP,i.uv0.y));
//////// 血量不足时候闪烁动画显示
float flash = 1;
if(_HP <= 0.2){
flash = 1 + cos(_Time.y*4) * 0.5;
}
bloodColor = bloodColor * flash;
// 背景的颜色
half4 bgColor = half4(0,0,0,1);
// 插值背景颜色和血量颜色
half4 endColor = lerp(bgColor,bloodColor,b);
return half4(endColor.rgb * borderMask,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
using UnityEngine;
public class ControlBloodScript : MonoBehaviour
{
public Material material;
void Start()
{
ChangeBi(0.5f);
}
public void ChangeBi(float value)
{
if(material == null)
{
material = GetComponent<MeshRenderer>().material;
}
material.SetFloat("_HP",value);
}
}
度盘:https://pan.baidu.com/s/13fxLg3j9xMGfKdpHEH1zhw?pwd=66a1 (opens new window)