一、文章简介

        在看完关于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,需要多积累。

        这些简单的案例,特别的简单,是因为很容易去理解,所以对于刚看过理论知识的,当做练习挺好。

Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐