Shader第二讲——我们来聊聊变量

今天的Shader课程我们来学习Unity中的Properties(变量)。我们学任何一门语言,首先是从变量开始学的,UnityShader也不例外。之前有学生问过我,Shader网上的例子教程好少啊,怎么学的好?其实Shader难学是大家普遍认可的,但是其实最好的学习方法就在我们身边,官方的Document里面有非常详细的Shader教程.


如果英文好的话,看官网就能差不多入门了,英语不好的同学,照着本课程学习下来,也能收获颇丰。
那么我们就开始进入正题。
首先来看看官方文档对Properties的定义:

Shaders can define a list of parameters to be set by artists in Unity’s material inspector,The Properties block in the shader file defines them.

这句话的意思就是Properties作为属性可以显示在Unity的材质球里面,他是Unity通向Shader的窗口。

怎么理解这句话呢?其实就是Unity用来和Shader进行交互的媒介,我们在外面定义Shader的值,在内部可以根据这值做相应变化,从而改变显示效果。我们来举个例子,在Unity2017里面新建一个Shader,选择Unlit,然后把上面的Properties删掉,换成下面的代码:

Properties
{
    _MainTex ("Texture", 2D) = "white" {}
    _MainTex3D("Texture3D",3D)="white"{}
    _Color("Color",color)=(1,0,0,1)
    _Float("Float",float)=0.0
    _Int("Int",int)=1
    _Range("Range",range(0,1))=0
    _Vector("Vector",vector)=(1,0,0,1)
    CubeMap("CubeMap",cube)="white"{}
}

接着我们把他赋予到随机一个材质球上,出来看看效果.

可以看到我们外面的材质球也做出了相应的变化。我们一行行来看看他们的意思。

  • 第一行,这里定义了一个变量_MainTex,_MainTex是变量的“真名”,“真名”在shader里面有很重要的作用,不单止可以和Unity进行交互,而且可以和下面CG语言里面的变量进行交互。而括号里面双引号括起来的是变量的“小名”,“小名”除了能在编辑器里面显示,就没有任何作用了,比如这里的Texture在编辑器的材质球左边就是Texture,注意:这里小名是可以支持中文的,也就是说如果你代码里面用了中文,材质球编辑器也会显示中文.

     _MainTex ("美术大大这里放上你画的贴图", 2D) = "white" {}
    

我们接着来看,后面的2D是变量的类型,这里这个2D是2D贴图的意思,也就是一般美术画的贴图,然后最后是默认值,white就是什么贴图都不给的时候他是什么颜色,可选的还有black,red,gray,同学们可以自行去尝试一下。

  • 第二行和上面的一样,不一样的是这里是3D类型的贴图,这种贴图一般出现在次世代里面,比较高级的贴图,Unity手游上面不做考虑,详细的同学可以自行去查阅相关资料

  • 第三行是Color,编辑器显示出来的是调色板,一般用来做颜色处理,可以用来给物体混合颜色。他的默认值这里给的是1,0,0,1,红色,对应的是颜色里面的RGBA,Red,Green,Blue和Alpha。

  • 第四行的是Float,一般用来处理一些数学计算,比如算高光强度,颜色强度等待,他和C#的float都是算4个字节,同时都支持小数。

  • 第五行的是Int,相对来说没那么大的作用,因为他不能计算小数部分,而在Shader里面,小数的计算是很普遍的,注意这里还有一个Bug,就是在编辑器里面,虽然他能用小数去赋值,但是他获取到的还是一个整数,感兴趣的同学可以自己试试。

  • 第六行的是Range,他其实就是Float,但是会比Float好用很多,因为他可以限制范围,通常用来调试一些比较复杂的计算,而不至于超出。他默认值我给的是0,注意这里默认值如果溢出,他将会取到最靠近的有效值。

  • 第七行是Vector,他其实是4个Float,如果有时候我们想传比较多的float值进来,我们可以尝试传4个Float,相对来说会比较方便,他的默认值我给的是(1,0,0,1),相对于的是X,Y,Z,W

  • 第八个是CubeMap,它是用来处理空间反射效果的变量,这里面只能丢CubeMap类型的贴图,在Project窗口按鼠标右键可以创建一个。而他是不能识别普通的2D贴图的。

那么问题来了?

我们C#怎么和Shader进行交互呢?

很简单,首先我们要知道我们的Shader是在Material(材质球)上面的,我们的Material(材质球)又是在MeshRenderer(网格渲染器)上面的.

我们在挂了该Shader的材质球上面写上这个代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour {

    private void Start()
    {
        this.GetComponent<MeshRenderer>().material.SetColor("_Color", Color.red);
    }
}

注意,这里如果我们要改颜色就SetColor,如果要改Float,就SetFloat,如果要改Texture,就SetTexture。
以此类推,那后面的变量填什么呢?你要改什么变量,就去Shader里面找他的“真名”(PS:现在知道“真名”的用处了吧)注意这里如果用“小名”是会不通过的,最后一个参数填上要改成的值就行了。

随着金光一闪,我们的Shader的变量成功被我们改掉了。但是还有一个问题,为啥我们的盒子还是白色呢?
哈哈,因为这里他们没有任何关系,盒子是根据贴图的方式去采样的,我们在输出颜色的片段着色器里面,需要把他改成根据_Color的颜色输出的才行。所以接下来改代码:

Shader "Unlit/MyShader"
{
    Properties
    {
        _MainTex ("美术大大这里放上你画的贴图", 2D) = "white" {}
        _MainTex3D("Texture3D",3D)="white"{}
        _Color("Color",color)=(1,0,0,1)
        _Float("Float",float)=0.0
        _Int("Int",int)=1
        _Range("Range",range(0,1))=0
        _Vector("Vector",vector)=(1,0,0,1)
        CubeMap("CubeMap",cube)="white"{}
    }
SubShader
{
    Tags { "RenderType"="Opaque" }
    LOD 100

    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        // make fog work
        #pragma multi_compile_fog
        
        #include "UnityCG.cginc"

        fixed4 _Color;

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

        struct v2f
        {
            float2 uv : TEXCOORD0;
            UNITY_FOG_COORDS(1)
            float4 vertex : SV_POSITION;
        };

        sampler2D _MainTex;
        float4 _MainTex_ST;
        
        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
            UNITY_TRANSFER_FOG(o,o.vertex);
            return o;
        }
        
        fixed4 frag (v2f i) : SV_Target
        {
            
            return _Color;
        }
        ENDCG
    }
}
}

注意我们中间有段代码Fixed4 _Color;

这里如果不写上的话SHADER不能用,原来上面没有分号的是SHADERLAB语法,下面有分号的是CG语法,两者属于不同的语法空间,所以上面定义的变量不能直接拿来用,要在下面写一个FIXED4 _COLOR映射过来(注意名字不能写错!!),FIXED是CG里面一个很重要的类型,是FLOAT的最小精度,他的取值范围是-2~2,刚好匹配颜色的范围。这里为啥用FIXED不用FLOAT,因为显卡的显存空间是很珍贵的,自行体会= =。其他变量要做映射的话也要注意,2D在CG里面要用SAMPLER2D,VECTOR在CG里面要用FLOAT4.

全套操作做完之后,我们应该能看到物体的颜色被我们改变了。

其实主要就是改动FragmentShader里面的代码,这个着色器是主要决定物体的颜色的。

那么下一章节,我们主要来研究一下FragmentShader,他是怎么改变物体的颜色的,同时我们还要基于片段着色器,做一个UV动画,让广告牌动起来。


(程序是个永无止境的东西,必须每天保持学习)

版权所有,违责必究

菜鸟在线 林老师 2017.9.17

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容