Unity Shader基础的使用:基础、法线贴图及光照模型代码的注释

发表于2017-11-08
评论0 2.5k浏览
话说之前是不是说暂时不研究Shader?没事哈,不要在意那么多细节,要的就是莽,疯狂加点就行了。

这边主要是把猫大写的Shader仔细注释了一下,以便以后查阅,暂时不系统的学习Shader。

Shader其实相当于一个后期的处理,在已经有的模型上加个特效什么的,让它的显示更加炫酷,Shader也算是学习Unity的一个重中之重。

下面发一下代码:
//一个基础的Shader  
Shader "Custom/Diffuse Texture" {  
    Properties {  
        /* 
         类型: 
         Color 一种颜色 
         2D 2的阶数大小的贴图 
         Rect 非2阶数大小的贴图 
         Cube 立方体纹理 
         Range(min, max) 介于最小值最大值的浮点数 
         Float 任意一个浮点数 
         Vector 一个四维数 
         */  
        _Color ("Color", Color) = (0,0,0,1) //一种颜色  
        _MainTex ("Albedo (RGB)", 2D) = "white" {}  //2阶数大小的贴图  
        _Glossiness ("Smoothness", Range(0,1)) = 0.5    //浮点数  
        _Metallic ("Metallic", Range(0,1)) = 0.0    //浮点数  
    }  
    SubShader {  
        /* 
         重要的Tags: 
         "RenderType"="Transparent" 透明、半透明像素渲染 
         "ForceNoShadowCasting"="True" 从不产生阴影 
         "Queue"="xxx" 渲染顺序队列,主要参数: 
                "Backgroung" 最早调用,用来渲染天空盒或者背景 1000 
                "Geometry" 渲染非透明物体,默认值 2000 
                "AlphaText" 用来渲染经过Alpha Test的像素(这个不太理解) 2450 
                "Transparent" 从后往前的顺序渲染透明物体 3000 
                "Overlay" 渲染叠加效果,渲染的最后阶段,镜头光晕之类 4000 
        */  
        Tags { "RenderType"="Opaque" }  //渲染非透明物时执行  
        LOD 200 //Level of Detail,该值不能小于unity中设定的值,我的工程中该值为0,而且最高只能设置为7(不是很明白)  
        CGPROGRAM   //脚本开始,这边用的是Cg/HLSL语言,主要用于Dx的程序,如果是运行在OpenGL上的程序,unity会转化为GLSL语言,或者可以选择直接写GLSL语言的Shader,但显然使用Cg\HLSL有更好的移植性  
        // surface表明是一个表面着色器,surf 代码名称,Standard 光照模型  
        #pragma surface surf Standard fullforwardshadows  
        // Shader模型的版本为3.0  
        #pragma target 3.0  
        sampler2D _MainTex; //需要处理的贴图放在这里,注意这里的_MainTex是前面声明过的属性  
        struct Input {  
            float2 uv_MainTex;  //算是一个长度为2的float数组,uv前缀表示贴图上点的二维坐标  
        };  
        half _Glossiness;  
        half _Metallic;  
        fixed4 _Color;  
        /* 
         SurfaceOutputStandard的结构(教程中的是SurfaceOutput,这边应该是U5的新特性吧) 
         struct SurfaceOutputStandard 
         { 
            fixed3 Albedo;  //漫反射颜色 
            fixed3 Normal;  //切线空间法线 
            half3 Emission; //自发光 
            half Metallic;  //金属度,0为非金属,1为金属 
            half Smoothness;    //光泽度,0为非常粗糙,1为非常光滑 
            half Occlusion; //遮挡(默认1) 
            fixed Alpha;    //透明度 
         } 
         SurfaceOutput中是Specular镜面高光、Gloss发光强度代替了Metallic、Smoothness、Occlusion 
        */  
        // 主处理函数,输入输出必须按规定写  
        void surf (Input IN, inout SurfaceOutputStandard o) {  
            // 对一个点进行采样  
            fixed4 c = tex2D(_MainTex, IN.uv_MainTex); //* _Color;  
            o.Albedo = c.rgb;  
            o.Metallic = _Metallic;  
            o.Smoothness = _Glossiness;  
            o.Alpha = c.a;  
        }  
        ENDCG   //脚本结束  
    }  
    FallBack "Diffuse"  
}  

//一个带法线贴图、光照模型的Shader  
Shader "Custom/Normal Mapping" {  
    Properties {  
        _MainTex ("Base (RGB)", 2D) = "white" {}    //原本的贴图  
        _Bump("Bump", 2D) = "bump"{}    //法线贴图  
        _Snow("Snow Level", Range(0, 1)) = 0    //雪等级  
        _SnowColor("Snow Color", Color) = (1.0, 1.0, 1.0, 1.0)  //雪颜色  
        _SnowDirection("Snow Direction", Vector) = (0, 1, 0)    //雪的方向  
        _SnowDepth("Snow Depth", Range(0, 0.3)) = 0.1   //雪的深度  
    }  
    SubShader {  
        Tags { "RenderType"="Opaque" }  
        LOD 200  
        CGPROGRAM  
        #pragma surface surf CustomDiffuse vertex:vert  //vertex:vert表明我们会改变顶点,并且会使用vert函数来做处理  
        // 定义自己的光照模型  
        //#pragma surface surf CustomDiffuse  
        /* 
         参数:SurfaceOutput 经过表面计算后的输入;lightDir 光线方向;atten 光衰减系数 
        */  
        half4 LightingCustomDiffuse(SurfaceOutput s, half3 lightDir, half atten) {  
            half difLight = max(0, dot(s.Normal, lightDir));    //点积调整当前点的亮度  
            difLight = difLight * 0.5   0.5;    //低光下增亮效果(半条命),范围从0-1到0.5-1  
            half4 col;  
            col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2); //根据物体的颜色、光颜色、光亮度、衰减度计算当前点的颜色,2是历史问题,U5中已经移除,但我们这边还保留着  
            col.a = s.Alpha;  
            return col;  
        }  
        sampler2D _MainTex;  
        sampler2D _Bump;  
        float _Snow;  
        float4 _SnowColor;  
        float4 _SnowDirection;  
        float _SnowDepth;  
        struct Input {  
            float2 uv_MainTex;  
            float2 uv_Bump;  
            float3 worldNormal; INTERNAL_DATA   //当前点在世界中的法线值  
        };  
        void vert(inout appdata_full v)  
        {  
            float4 sn = mul(transpose(_Object2World), _SnowDirection);  //把积雪方向的矩阵转换到世界矩阵  
            if (dot(v.normal, sn.xyz) >= lerp(1, -1, (_Snow * 2) / 3))  
            {  
                v.vertex.xyz  = (sn.xyz   v.normal) * _SnowDepth * _Snow;  
            }  
        }  
        void surf (Input IN, inout SurfaceOutput o) {   //使用自己的光照模型时,参数为SurfaceOutput,而不是SurfaceOutputStandard  
            half4 c = tex2D(_MainTex, IN.uv_MainTex);  
            o.Normal = UnpackNormal(tex2D(_Bump, IN.uv_Bump));  
            // 世界中的法线方与垂直方向做点积,计算出1到-1的值,如果大于雪的阈值,则显示白色  
            if (dot(WorldNormalVector(IN, o.Normal), _SnowDirection.xyz) > lerp(1, -1, _Snow))  
            {  
                o.Albedo = _SnowColor.rgb;  
            }  
            else  
            {  
                o.Albedo = c.rgb;  
            }  
            o.Alpha = c.a;  
        }  
        ENDCG  
    }  
    FallBack "Diffuse"  
}  

基本上来说,跟猫大那时候的版本差不多,不过注意的是Unity5.0时代基础创建的Shader使用的是Standard的一个光照模型,所以这边要注意一下,我在代码中也有标明。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引