当前位置:   article > 正文

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

unity shader案例解析

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;         //透明度系数
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

看完很蒙?
那就对了。。。说明我不是一个人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
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

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

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

剩下的不管有没有提到 都会在接下来的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"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

这个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"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

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

本节就到这里吧

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/107878
推荐阅读
相关标签
  

闽ICP备14008679号