找回密码
 立即注册
查看: 376|回复: 0

[笔记] Unity5的Shader体系简析

[复制链接]
发表于 2023-1-2 16:29 | 显示全部楼层 |阅读模式
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"
}
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-12-22 11:06 , Processed in 0.089103 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表