前言

借由 Unity Shader 实战学习 Shader !
带完整注释,一起学习 💪


效果

指定颜色渐变的效果,可以设置渐变开始及结束的位置

👉展示备份(国内节点)
👇效果展示(科学上网)


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
Shader "Unlit/AloeaShader01"
{
Properties
{
_StartColor ("Start Color", Color) = (1,1,1,1) // 定义传入起始颜色
_EndColor ("End Color", Color) = (0,0,0,0) // 定义传入结束颜色
_StartPos ("Start Postion", Range(0,1)) = 0 // 定义传入起始位置
_EndPos ("End Position", Range(0,1)) = 1 // 定义传入结束位置

}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100

Pass
{
CGPROGRAM
#pragma vertex vert // 声明顶点着色器的方法
#pragma fragment frag // 声明片段着色器的方法

#include "UnityCG.cginc" // 引用 CG 包

float4 _StartColor; // 变量引入
float4 _EndColor; // 变量引入
float _StartPos; // 变量引入
float _EndPos; // 变量引入

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};


v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); // 本地空间转化为相机的剪辑空间
o.uv = v.uv; // 传递uv信息
return o;
}

// a b 定义线性数值的范围,计算 v 在此范围内的位置
float InverserLerp (float a, float b, float v) {
return (v-a)/(b-a);
}

fixed4 frag (v2f i) : SV_Target
{
float4 t = InverserLerp(_StartPos, _EndPos, i.uv.x); // 把 v 约束在 a ~ b 之间
float4 outColor = lerp(_StartColor, _EndColor, t); // 按照 t 插值
return outColor;
}
ENDCG
}
}
}


细节

🤔 颜色过渡不正常

颜色过渡不正常需要修改下工程的色彩空间计算方式,从 Linear 改为 gamma,原因可以看我这篇的科普。
位置在 Edit > Project Settings,搜索 Rendering
image.png


🤔 Lerp 函数 可视化理解


Lerp,A 和 B 之间按照 Alpha 线性插值。

1
( ( 1 - A ) * Alpha + B * Alpha)

🤔 InverserLerp 函数 可视化理解

2.gif.4d6f47d385d2b8ccd3d70c0c7389082e.gif
InverserLerp,v 值在 a ~ b 范围内对应比例的值。
参考上图理解,a ~ b指定为 20 ~ 10,v 是 0 ~ 35。当 v 为 10 时,结果为 1;当 v 为 15 时,结果为 0.5;当 v 为 20 时,结果为0。

1
( v - a ) / ( b - a )  

🤔 单位精度

float:32位浮点数,全浮。最高精度,建议用于世界空间位置,纹理坐标,复杂计算如幂/指数等。
half:16位浮点数,半浮。数值范围 [-60000, +60000],建议用于方向、HDR 颜色等。
fixed:11位浮点数,低精度。数值范围 [-2, +2],用于低精度的运算变量。

注意以上是通常情况,实际各种硬件设备可能会有自己特别的定义,比如浮点精度特殊,或者根本就没有 half、fixed,总之精度的机制最终就是退会 float。

Unity Shader的数据类型和 HLSL 略有不同,针对移动平台做了优化。