运行环境:
Win10 x64
Unity 5.5.4
在场景中创建一个cube,使它的颜色产生简单的两种颜色过渡的渐变效果,如下图:
先说一下CG语言中的lerp函数
lerp(a, b, w);
a与b为同类形,即都是float或者float2之类的,那lerp函数返回的结果也是与ab同类型的值。
w是比重,在0到1之间
当w为0时返回a,为1时返回b,在01之间时,以比重w将ab进行线性插值计算。
功能很简单,实现也很简单。
Shader代码:
Shader "Custom/TestRedYellow" {
Properties{
_MainColor("MainColor", color) = (0,1,0,1) //第一种颜色:绿
_SecondColor("SecondColor", color) = (1,0,0,1) //第二种颜色:红
_Center("Center", range(-0.51,0.51)) = 0 //中心点y坐标值
_R("R", range(0,1)) = 0.2 //产生渐变的范围值
}
SubShader {
pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
fixed4 _MainColor;
fixed4 _SecondColor;
float _Center;
float _R;
struct v2f {
float4 pos:POSITION;
float y : TEXCOORD0;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.y = v.vertex.y;
return o;
}
fixed4 frag(v2f IN):COLOR
{
float y = IN.y;
float s = y -( _Center - _R/2);
float f = saturate(s / _R);
fixed4 col = lerp(_MainColor, _SecondColor, f);
return col;
}
ENDCG
}
}
}
对y值的判断和颜色的插值要写在片断程序中才能产生图上的渐变效果,写在顶点程序中是不行的,因为只有八个角八个顶点,非红即绿,不会有颜色渐变。
但是要在顶点程序中获取物体坐标系下的y坐标,所以结构体中定义了y,且在顶点程序中赋值:
o.y = v.vertex.y;
再在片断程序中获取:
float y =IN.y;
以_R为范围,其实是在中心点_Center两端从-R/2到R/2这个范围中
这个颜色渐变的范围的起点应该是:(_Center-R/2)。
float s = y -( _Center - _R/2);
(注意:Center-R/2为颜色渐变的范围的起点y坐标,或者说是范围的下端点坐标,范围长度是_R。
这个起点可以根据需要自己调整,也可以就是_Center,或者别的值。)
代码中插值函数的比重 f为:
float f = saturate(s / _R);
当s<0时,即y坐标在_Center以下,且距_Center大于_R/2的距离,f=0,则返回的颜色为_MainColor,即我们定义的绿。
当s>_R时,即y坐标在_Center以上,且距_Center大于_R/2的距离,f=1,则返回的颜色为_SecondColor,即我们定义的红。
这样,最终结果为,以cube的y坐标_Center为中心,以长度为_R的(_Center-_R/2, _Center+_R/2)为范围,对_MainColor和_SecondColor进行渐变处理。小于此范围的显示_MainColor,大于此范围的显示_SecondColor。
Unity的Inspector面板中的材质:
我们将中心点_Center设置为0,即cube中心,渐变范围_R设置为1
这样就能实现cube从下至上整体的从绿到红的颜色渐变了(看起来效果比较明显)
将_R调节至0,即渐变范围为0,不渐变
绿到红没有任何过度,有明确的分界线