UnityShader——简单案例
使用UnityShader完成渐变材质和顶点水波纹效果
一、文章简介
在看完关于Unity Shader的书还有听课之后,发现学习了很多理论知识。但是对于自己写还差点距离,感觉没有很多的思路,此文章写一些简单的案例,方便刚入门的去理解。可以直接上手,写Shader。
二、案例
1、渐变材质
首先看一下效果:
很明显,我们的第一个效果就是渐变,这是挂载到一个球体上的,接下来我们就看代码。
Shader "Custom/Colorful"
{
SubShader
{
pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include"UnityCG.cginc"
struct v2f
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
v2f vert(v2f v)
{
v.vertex = UnityObjectToClipPos(v.vertex);
return v;
}
fixed4 frag(v2f o) : SV_Target
{
float3 n = o.normal / 2 + float3(0.5,0.5,0.5);
return float4(n,1);
}
ENDCG
}
}
}
我们都知道,每个顶点都有一条法线,对于球体来说,法线就会很奇妙,每个顶点的法线都不同,而且会以一个渐变的方式偏移。
我们会发现,球体上法线的偏移,相邻的顶点法线偏移很小,那么我们这个渐变就是基于法线的变换的。所以上边代码中,在顶点函数(Vertex)中,我们进行顶点坐标的转换。在片元函数(Fragment)中,我们定义了一个变量n,进行接收对法线的操作数据。那么就会有一个疑惑点了,那就是关于这一块的代码。
如果看过《入门精要》的可能明白这个操作是干嘛的。
首先,我们要知道法线的取值范围[-1,1]。然后就是颜色的[0,1]。我们现在要用法线的数据去改变颜色,所以肯定要把法线的[-1,0]的地方转换为[0,1]的区间内,不然我们生成出的渐变材质就会比较丑陋,这是因为我们把法线的数据切除了一半。所以我们用这个操作去转换区间。大家也可以去计算一下,试一下负数部分进行完这个操作后能不能变成正数。
可能有人会说,saturate这个函数。这个函数就跟上边所说的对半砍差不多的。小于0的值,返回0。大于0的值x,返回x。
2、顶点水波纹
因为此篇是很简单的案例,所以这里的水波纹,就是顶点随时间变化发生波动的。
当然,代码也是非常的简单,但是我感觉,对于还在看书学习Shader的还是比较有用的,至少能增加一点信心。
下边看代码:
Shader "Custom/Shader_water"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
float dis = distance(v.vertex.xyz,float3(0,0,0));//每个坐标与0的距离
float h = sin(dis * 2 + _Time.z) / 5;// *2 加波峰数量 /5 减振幅
o.vertex = mul(unity_ObjectToWorld,v.vertex);//模型空间转世界空间
o.vertex.y = h;
o.vertex = mul(unity_WorldToObject,o.vertex);//世界空间转模型空间
o.vertex = UnityObjectToClipPos(o.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);//根据顶点的纹理坐标 计算出对应的纹理的
真正的UV坐标
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
上边的代码,基本就是对坐标空间转换,然后求值。最主要的逻辑是对于变量h的求值。
其中的2和5也是控制波峰和振幅的。所以整体逻辑还是很简单的。sin就是波动的方式,按照sin波进行一个波动。关于_Time的使用,
_Time.x (t/20) _Time.y (t)
_Time.z (t * 2) _Time.w (t * 3)
三、小结
关于Shader,需要多积累。
这些简单的案例,特别的简单,是因为很容易去理解,所以对于刚看过理论知识的,当做练习挺好。
更多推荐
所有评论(0)