UnityShader官方案例讲解——SurfaceShader(1)

Living without an aim is like sailing without a compass.(John Ruskin)

接下来要做的就是对官方的着色器案例进行讲解,本着学习的态度,我会尽量解释每一行代码,因为还没有毕业,剩下的时间比较多,我会写的比较详细(慢&懒)

因为我也是新手,所以我很理解新手的痛处吗,在一开始我不会一下子列出好多好多的语法,或者是好多 好多的关键字,咱们一起从例子中不断的学习,虽然很慢,但是shader这条路是没有捷径的

若有不足之处 还望路过的前辈们不吝赐教(拱手状 O(∩_∩)O)

突然发现自己学和写出来一步一步进行讲解真的很不一样,应该是技术水平过于拙劣吧

step1
从最基础讲SurfaceShader,需要介绍其常用的标准的表面着色器输出结构(SurfaceOutput)

struct SurfaceOutput
{
    half3 Albedo;       //表面着色器当中常于做漫反射的颜色值,也就是SurfaceShader常用来进行输出的颜色值
    half3 Normal;       //游戏物体(mesh)的表面法线坐标
    half3 Emission;     //自发光颜色
    half Specular;      //镜面高光
    half Gloss;         //光泽系数
    half Alpha;         //透明度系数
};

看完很蒙?
那就对了。。。说明我不是一个人O(∩_∩)O哈哈~(狂笑)

没关系,大家先放一放,紧接着会在案例中对这些属性及其作用进行讲解,先有个印象好了

step2
表面着色器的编译指令
我们在写vertex&*fragment shader 时 经常会为其指定一个通道进行渲染,但是SurfaceShader不可以放在通道(pass)内,因为表面着色器会自身编译为多个通道。

Shader"Example / AutisticPatient SurfaceShader1"
{
    SubShader
    {
        CGPROGRAM
        //表面着色器编译指令, #pragma + surface + surfaceFunction + LightModle 
        //这里指定了unity3D的内建光照模型:Lambert
        #pragma surface surf Lambert

        //其中“Input”是自定义的结构。Input 结构应包含表面函数所需的任何纹理坐标和额外自动变量。
        //SurfaceOutput刚才说了 是表面着色器标准输出结构体,这里Input将作为输入结构体,SurfaceOutput将用于输出
        void surf(Input IN, SurfaceOutput o)
        {

        }



        ENDCG
    }
}

step3
表面着色器的输入结构体
下面是一部分可以放在输入结构体当中的值

    struct Input
        {
            float2 uv_MainTex;              //主纹理UV坐标值
            float2 uv2_MainTex;             //使用第二纹理坐标值
            float3 viewDir;                 //包含视线方向
            float4 screenPos;               //屏幕空间位置
            float3 worldPos;                // 将包含世界坐标空间位置。
        };

剩下的不管有没有提到 都会在接下来的shader实例中进行讲解

表面着色器实例

(1)
因为是对官方案例的讲解,所以就按照官方的顺序来,我会逐句进行解释
并配上效果图供大家参考(图片是Down的)

从一个简单的SurfaceShader开始

Shader"Example / AutisticPatient SurfaceShader2"
{
    //刚开始官方给的是一个不需要纹理的shader,所以这里并没有大家常见的Properties
    //开始一个子shader
    SubShader
    {   
        //Tags 用来指示渲染引擎如何渲染,以及何时渲染。+ 标签有多种,灯光标签,队列标签等
        //这行代码的意思是此shader渲染不透明对象
        //RenderType tag 是渲染标签,它常用的有:
        //Opaque
        //Transparent
        //TransparentCutout
        //Background
        //Overlay
        Tags{"RenderType" = "Opaque"}
        //开始CG
        CGPROGRAM
        //定义表面着色器,并指定了unity内置的光照模式lambert(漫反射光照模式)
        #pragma surface surf Lambert

        //表面着色器输入结构体
        //为什么里面能写颜色值上边已经说过了
        struct Input
        {
             float4 color : COLOR;
        };

        //这个函数便是我们上面定义好的表面着色器 名称一定要完全相同.
        //然后将我们定义好的输入结构体放进去
        //想要使得表面着色器能够输出我们想要的颜色值,还必须将标准的表面着色器结构体作为输出放进形参内.
        //这里使用了inout关键字,意思是 SurfaceOutput结构体中传进来的参数既作输入也做输出.
        void surf(Input IN,inout SurfaceOutput o)
        {
            //相当于o.Albedo = (1,1,1)不要问为啥了吧(痛哭状)
            o.Albedo = 1;   
            //所以最后整个表面着色函数输出的便是SurfaceOutput下的Albedo值了.
        }


        ENDCG
    }

    //这里需要设置一个备胎着色器,如果以上着色器不能被设备支持 
    //便会使用下面的Diffuse着色器
    fallback"Diffuse"
}

这个shader就不上效果图了,实在是没啥可看的,咳咳~

(2)
接下来是有纹理贴图的shader

Shader"Example / AutisticPatient SurfaceShader3"
{
    //属性块,这一代码块中定义的属性是对整个shader的定义(这句话可能不太恰当)
    //比如说,我们想要一个融化效果,那么在shader中肯定会有融化纹理以及主纹理的定义
    //还有包括融化速度,融化边缘效果等等,这些属性都是要在Properties中进行定义的
    Properties
    {
        //_MainTex的作用是关联整个shader代码,下面我们会在CG中进行关联,只有关联上,我们才能对这个纹理进行修改等操作
        //"MainTex" 的作用是在Inspector面板中创建一个可视化操作台,方便开发者在外部进行修改贴图,不需要修改shader.
        //2D的作用的指定我们所定义的对象的类型,这里是指2D纹理类型,如果你想定义一个贴图,那么就要用到它了
        //等号后面,不说了,就是初始化而已
        _MainTex("MainTex",2D) = "white"{}
    }

    SubShader
    {
        Tags{"RenderType" = "Opaque"}
        CGPROGRAM
        #pragma surface surf Lambert

        //输入结构体用于描述贴图的uv坐标,只有得到了uv坐标,才能对纹理进行采样等操作
        struct Input
        {
            //命名格式 uv + _MainTex
            float2 uv_MainTex;
        };

        //properties里已经说过了,想要对纹理贴图进行操作,就必须关联上
        //而为什么用sampler2D呢 
        //如果在Properties使用2D,CG里要用sampler2D,代表使用的是2维纹理
        //这是王八的屁股,规定(龟腚)
        sampler2D _MainTex;

        void surf(Input IN,inout SurfaceOutput o)
        {
            //tex2D是CG程序中用来对一张贴图(这里是_MainTex)中对一个点(IN.uv_MainTex)进行采样的方法
            //返回一个float4类型,并将其颜色的rgb值赋给了输出的像素颜色
            //总的来说,着色器会找到贴图上对应的UV坐标点,直接使用这个点的颜色信息rgb来进行着色.
            o.Albedo = tex2D(_MainTex,IN.uv_MainTex).rgb;
        }

        ENDCG
    }
    FallBack"Diffuse"
}

这里写图片描述
ok 上个效果图先
这里写图片描述

本节就到这里吧

刚开始有很多细节是不能跳过的,所以注释会显得过于冗长(其实就是表达能力弱(。・・)ノ)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值