ChuanXin 发表于 2023-1-2 16:29

Unity5的Shader体系简析

1.标准表面着色器(Standard Surface Shader)模板源码解析
在Unity中,我们若要实现新的表面着色器时,可以根据这个模板,进行一步添加子着色器和新的参数与特性。
这个Shader模板的脉络很清晰,先是定义一些属性,然后在SubShader中设置渲染模式,层次细节LOD的值,然后开启一个CG编程语言模块,写一些编译指令#pragma,声明一下变量让属性值在CG块中可见,定义输入结构,然后填充一下表面着色函数即可。注意:专门强调一句,SurfaceShader不能使用Pass,一使用就报错,我们直接在SubShader中实现和填充代码就可以了。
Standard Surface Shader模板详细注释的Shader代码如下:
//表面着色器 内部包含很多内置函数 计算   使用起来非常方便适合新手
Shader "Shader( 名字)/Volume8/Surface Shader模板"
{
       //------------------------------------【属性值】------------------------------------
       //添加需要shader需要属性
       Properties
       {
            //主颜色
            _Color("Color", Color) = (1,1,1,1)
            //主纹理
            _MainTex("Albedo (RGB)", 2D) = "white" {}
            //光泽度
            _Glossiness("Smoothness", Range(0,1)) = 0.5
            //金属度
            _Metallic("Metallic", Range(0,1)) = 0.0
       }
   
       //------------------------------------【子着色器】------------------------------------
       SubShader
       {
            //【注意:Surface Shader不能使用Pass,直接在SubShader中实现即可】
   
            //渲染类型设置:不透明   ()
            Tags{"RenderType" = "Opaque" }
   
            //细节层次设为:200
            LOD200
   
            //===========CG着色器语言编写模块===========
            CGPROGRAM
   
            //编译指令:告知编译器表明着色函数的名称为surf
            //Standard表示光照模型为Unity标准版光照模型
            //fullforwardshadows表示在正向渲染路径中支持所有阴影类型
            #pragma surface surf Standard fullforwardshadows
   
            //编译指令: 指定着色器编译目标为Shader Model 3.0
            #pragma target 3.0
   
            //变量的声明
            sampler2D _MainTex;
   
            //表面输入结构体
            struct Input
            {
                  float2 uv_MainTex;//纹理坐标
            };
   
            //变量的声明
            half _Glossiness;
            half _Metallic;
            fixed4 _Color;
   
            //--------------------------------【表面着色函数】-----------------------------
            //输入:表面输入结构体
            //输出:Unity内置的SurfaceOutputStandard结构体
            //SurfaceOutputStandard原型如下:
            /*
                     struct SurfaceOutputStandard
                     {
                            fixed3 Albedo;                  // 漫反射颜色
                            fixed3 Normal;                  // 切线空间法线
                            half3 Emission;               //自发光
                            half Metallic;                           // 金属度;取0为非金属, 取1为金属
                            half Smoothness;             // 光泽度;取0为非常粗糙, 取1为非常光滑
                            half Occlusion;               // 遮挡(默认值为1)
                            fixed Alpha;                      // 透明度
                     };
            */
            //-----
            void surf(Input IN, inout SurfaceOutputStandard o)
            {
                     //【1】漫反射颜色为主纹理对应的纹理坐标,并乘以主颜色
                     fixed4c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
                     //【2】将准备好的颜色的rgb分量作为漫反射颜色
                     o.Albedo= c.rgb;
                     //【3】金属度取自属性值
                     o.Metallic= _Metallic;
                     //【4】光泽度也取自属性值
                     o.Smoothness= _Glossiness;
                     //【5】将准备好的颜色的alpha分量作为Alpha分量值
                     o.Alpha= c.a;
            }
   
            //===========结束CG着色器语言编写模块===========
            ENDCG
       }
       //备胎为漫反射
       FallBack"Diffuse"
}

2.无灯光着色器(Unlit Shader)模板源码解析
Unlit Shader,简单来说,就是直接采用漫反射纹理,不考虑场景中的任何灯光效果。使用无灯光着色器的话,也就不能使用任何镜面或者法线效果了。Unlit系的Shader基本原理和其他Shader无异,但是计算量更小,更快速,更高效。
下面一起看一下Unity为我们提供的无灯光着色器模板的代码
Shader "无灯光着色器(Unlit Shader)模板"
{
       //------------------------------------【属性值】------------------------------------
       Properties
       {
            //主纹理
            _MainTex("Texture", 2D) = "white" {}
       }
   
       //------------------------------------【子着色器】------------------------------------
       SubShader
       {
            //渲染类型设置:不透明
            Tags{ "RenderType"="Opaque" }
   
            //细节层次设为:100
            LOD 100
   
            //--------------------------------唯一的通道-------------------------------
            Pass
            {
            //Always: 总是渲染;没有光照模式。
            //ForwardBase: 适用于前渲染、环境、主要方向灯、光/sh光和烘焙图。
            //ForwardAdd: 适用于前渲染, 叠加每一盏灯,每一盏灯就多一个pass。
            //Deferred: 延迟渲染,渲染g缓冲区 。
            //ShadowCaster:将物体深度渲染到阴影贴图或者深度纹理上 。
            //PrepassBase: 用于传统的延迟光照,渲染法线和高光效果。
            //PrepassFinal:用于传统的延迟光照,通过结合文理、灯光、和法线来渲染最终的结果。
            //Vertex:当对象不是光映射时,用于遗留顶点的渲染,所有顶点灯都被利用。
            //VertexLMRGBM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是RGBM编码的平台上(pc和控制台)。
            //VertexLM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是双idr编码的(移动平台)平台上。

                     //===========开启CG着色器语言编写模块===========
                     CGPROGRAM
   
                     //编译指令:告知编译器顶点和片段着色函数的名称
                     #pragma vertex vert
                     #pragma fragment frag
   
                     //着色器变体快捷编译指令:雾效。编译出几个不同的Shader变体来处理不同类型的雾效(关闭/线性/指数/二阶指数)
                     #pragma multi_compile_fog
         //衰减与阴影的实现
            #include "AutoLight.cginc"//
            //fwdadd:ForwardBase的阴影显示,在下面的ForwardAdd里得用fwdadd; 必须结合fallback,两者缺一不可

                     //包含头文件
                     #include"UnityCG.cginc"
   
                     //顶点着色器输入结构
                     struct appdata
                     {
                            float4 vertex : POSITION;//顶点位置
                            float2 uv : TEXCOORD0;//纹理坐标
                     };
   
                     //顶点着色器输出结构
                     struct v2f
                     {
                            float2 uv : TEXCOORD0;//纹理坐标
                            UNITY_FOG_COORDS(1)//雾
                            float4 vertex : SV_POSITION;//像素位置
                      LIGHTING_COORDS(3,4)//#include "AutoLight.cginc"

                     };
   
                     //变量声明
                     sampler2D _MainTex;
                     float4 _MainTex_ST;
                     
                     //--------------------------------【顶点着色函数】-----------------------------
                     //输入:顶点输入结构体
                     //输出:顶点输出结构体
                     //---------------------------------------------------------------------------------
                     v2f vert (appdata v)
                     {
                            //【1】实例化一个输入结构体
                            v2f o;
                            //【2】填充此输出结构
                            //输出的顶点位置(像素位置)为模型视图投影矩阵乘以顶点位置,也就是将三维空间中的坐标投影到了二维窗口
                            o.vertex= mul(UNITY_MATRIX_MVP, v.vertex);
                            //【3】用UnityCG.cginc头文件中内置定义的宏,根据uv坐标来计算真正的纹理上对应的位置(按比例进行二维变换)                  
                            o.uv= TRANSFORM_TEX(v.uv, _MainTex);
               //点光源需要的衰减
               TRANSFER_VERTEX_TO_FRAGMENT(o)//#include "AutoLight.cginc"

                            //用UnityCG.cginc头文件中内置定义的宏处理雾效,从顶点着色器中输出雾效数据
                            UNITY_TRANSFER_FOG(o,o.vertex);
   
                            //返回此输出结构对象
                            return o;
                     }
                     
                     //--------------------------------【片段着色函数】-----------------------------
                     //输入:顶点输出结构体
                     //输出:float4型的像素颜色值
                     //---------------------------------------------------------------------------------
                     fixed4 frag (v2f i) : SV_Target
                     {
                            //【1】采样主纹理在对应坐标下的颜色值
                            fixed4 col = tex2D(_MainTex, i.uv);
   
                            //【2】用UnityCG.cginc头文件中内置定义的宏启用雾效
                            UNITY_APPLY_FOG(i.fogCoord,col);            
   
                            //【3】返回最终的颜色值
                            return col;
                     }
   
               
                     ENDCG
            }
       }
      //需要产生阴影      调用备用材质
            FallBack "Diffuse"
}
页: [1]
查看完整版本: Unity5的Shader体系简析