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

来源:互联网 发布:淘宝买家信誉等级查询 编辑:程序博客网 时间:2024/06/18 00:09

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 上个效果图先
这里写图片描述

本节就到这里吧

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

0 0
原创粉丝点击