美文网首页
Unity内置Shader解读11——VertexLit

Unity内置Shader解读11——VertexLit

作者: ShawnWeasley | 来源:发表于2021-05-13 08:45 被阅读0次

    1.Shader在什么情况下使用

    VertexLit作为大部分shader的FallBack,实现了基础的光照、Lightmapped和阴影三个Pass。

    2.Shader的价值(用的多不多),Shader的难度

    直接用的可能不多,但绝大部分shader最终都FallBack到了这里,难度中,阴影部分还没搞清楚

    3.代码详细注释

    Shader "Legacy Shaders/VertexLit" {
        Properties {
            _Color ("Main Color", Color) = (1,1,1,1)
            _SpecColor ("Spec Color", Color) = (1,1,1,1)//镜面反射
            _Emission ("Emissive Color", Color) = (0,0,0,0)//自发光
            [PowerSlider(5.0)] _Shininess ("Shininess", Range (0.01, 1)) = 0.7//光泽度
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
    
        SubShader {
            Tags { "RenderType"="Opaque" }
            LOD 100
    
            // Non-lightmapped
            Pass {
                Tags { "LightMode" = "Vertex" }
                //使用最基础的渲染模式Fixed Shader实现基础效果
                Material {
                    Diffuse [_Color]
                    Ambient [_Color]
                    Shininess [_Shininess]
                    Specular [_SpecColor]
                    Emission [_Emission]
                }
                Lighting On
                SeparateSpecular On
                SetTexture [_MainTex] {
                    constantColor (1,1,1,1)
                    Combine texture * primary DOUBLE, constant // UNITY_OPAQUE_ALPHA_FFP
                }
            }
    
            // Lightmapped
            Pass
            {
                Tags{ "LIGHTMODE" = "VertexLM" "RenderType" = "Opaque" }
    
                CGPROGRAM
    
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 2.0
                #include "UnityCG.cginc"
                #pragma multi_compile_fog
                #define USING_FOG (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))
    
                float4 unity_Lightmap_ST;
                float4 _MainTex_ST;
    
                struct appdata
                {
                    float3 pos : POSITION;
                    float3 uv1 : TEXCOORD1;
                    float3 uv0 : TEXCOORD0;
                    UNITY_VERTEX_INPUT_INSTANCE_ID
                };
    
                struct v2f
                {
                    float2 uv0 : TEXCOORD0;
                    float2 uv1 : TEXCOORD1;
                    float2 uv2 : TEXCOORD2;
                    #if USING_FOG
                        fixed fog : TEXCOORD3;
                    #endif
                    float4 pos : SV_POSITION;
                    UNITY_VERTEX_OUTPUT_STEREO
                };
    
                v2f vert(appdata IN)
                {
                    v2f o;
                    UNITY_SETUP_INSTANCE_ID(IN);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    
                    //获取Lightmap的UV
                    //将模型顶点的uv和Tiling、Offset两个变量进行运算,计算出实际显示用的顶点uv
                    //乘以Tiling再加Offset
                    o.uv0 = IN.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
                    //o.uv1完全没有使用到,不知道这里写了有啥用,知道大佬麻烦告知下
                    o.uv1 = IN.uv1.xy * unity_Lightmap_ST.xy + unity_Lightmap_ST.zw;
                    //获取主纹理的UV
                    o.uv2 = IN.uv0.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    
                    #if USING_FOG
                        //转到View空间下
                        float3 eyePos = UnityObjectToViewPos(IN.pos);
                        //length返回输入向量的长度,离view点越近的点雾效越淡
                        float fogCoord = length(eyePos.xyz);
                        //计算雾浓度
                        //具体可参考:https://blog.csdn.net/zengjunjie59/article/details/112346424
                        UNITY_CALC_FOG_FACTOR_RAW(fogCoord);
                        //限制o.fog值从0-1
                        o.fog = saturate(unityFogFactor);
                    #endif
    
                    //MVP转换
                    o.pos = UnityObjectToClipPos(IN.pos);
                    return o;
                }
    
                sampler2D _MainTex;
                fixed4 _Color;
    
                fixed4 frag(v2f IN) : SV_Target
                {
                    fixed4 col;
    
                    //采样Lightmap
                    fixed4 tex = UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv0.xy);
                    //DecodeLightmap解码光照贴图 
                    half4 bakedColor = half4(DecodeLightmap(tex), 1.0);
    
                    //将烘焙结果和_Color混合
                    col = bakedColor * _Color;
    
                    //采样主纹理
                    tex = tex2D(_MainTex, IN.uv2.xy);
                    //将col和主纹理颜色混合
                    col.rgb = tex.rgb * col.rgb;
    
                    //alpha控制为1
                    col.a = 1.0f;
    
                    #if USING_FOG
                        //混合雾效
                        col.rgb = lerp(unity_FogColor.rgb, col.rgb, IN.fog);
                    #endif
    
                    return col;
                }
    
                ENDCG
            }
    
            //VertexLit作为所有需要阴影的shader的FallBack,其实所有的阴影都是走的这个Pass
            // Pass to render object as a shadow caster 传递以将对象渲染为阴影投射器
            Pass {
                Name "ShadowCaster"
                Tags { "LightMode" = "ShadowCaster" }
    
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #pragma target 2.0
                #pragma multi_compile_shadowcaster
                #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders允许大多数着色器使用实例化shadow pass
                #include "UnityCG.cginc"
    
                struct v2f {
                    //阴影宏定义,主要定义了float4 pos:SV_POTISION;
                    V2F_SHADOW_CASTER;
                    //INSTANCE_ID
                    UNITY_VERTEX_OUTPUT_STEREO
                };
    
                v2f vert( appdata_base v )
                {
                    v2f o;
                    //INSTANCE_ID
                    UNITY_SETUP_INSTANCE_ID(v);
                    UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    
                    //Unity提供的阴影计算方法,搜不到解释,只有这篇解释了一半https://blog.csdn.net/yanyangxu01/article/details/81987064
                    //既然大家都不求甚解只管用,我也先放一放吧能力还不够-。-,后面有能力了再开专篇讲吧
                    TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
                    return o;
                }
    
                float4 frag( v2f i ) : SV_Target
                {
                    //同上
                    SHADOW_CASTER_FRAGMENT(i)
                }
                ENDCG
    
            }
        }
    }
    

    4.Shader编写思路,用到的知识点

    第一个Pass使用Fixed Shader实现基础的光照,第二个实现Lightmapped,最后一个实现阴影,作为绝大部分shader的FallBack终点,其实很多阴影都是用的这边的pass。知识点不太多,主要是阴影部分还没搞明白,也搜不到太多的资料,后面再更吧。


    Legacy Shaders基本已经讨论完了,同类型相似的不再赘述。

    相关文章

      网友评论

          本文标题:Unity内置Shader解读11——VertexLit

          本文链接:https://www.haomeiwen.com/subject/llmadltx.html