• 基本光照模型简单实现


    Lambert光照模型,根据光照向量与顶点法线的夹角来确定光照强度:

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "James/Lambert"
    {
        Properties
        {
            _MainTex("MainTex", 2D) = "white" {}
        }
            SubShader
        {
            Pass
            {
                Tags { "LightMode" = "ForwardBase" }
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
    
                fixed4 _LightColor0;
                sampler2D _MainTex;
                float4 _MainTex_ST;
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    float2 uv : TEXCOORD0;
                    float3 lightDir : TEXCOORD1;
                    float3 normal : TEXCOORD2;
                };
    
                v2f vert(appdata_full v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    // 从顶点位置到Light的局部向量
                    o.lightDir = ObjSpaceLightDir(v.vertex);
                    o.normal = v.normal;
                    return o;
                }
    
                float4 frag(v2f i) : COLOR
                {
                    i.lightDir = normalize(i.lightDir);
                    i.normal = normalize(i.normal);
                    // 纹理采样
                    float4 c = tex2D(_MainTex, i.uv);
                    // 光强度,法向和光照方向的cos值
                    float diffuse = max(0, dot(i.normal, i.lightDir));
                    // 纹理色 * 光源色 * 强度参数
                    c = c * _LightColor0 * diffuse;
                    return c;
                }
                ENDCG
            }
        }
            FallBack "Diffuse"
    }

    Phong光照模型,根据光照向量的反射向量与视线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "James/Phong"
    {
        Properties
        {
            _MainTex("MainTex", 2D) = "white" {}
            _Gloss("Gloss", Float) = 1
            _Shininess("Shininess", Float) = 10
            _SpecColor("Specular Color", Color) = (1,1,1,1)
        }
        SubShader
        {
            Pass
            {
                Tags { "LightMode" = "ForwardBase" }
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
    
                fixed4 _LightColor0;
                sampler2D _MainTex;
                float4 _MainTex_ST;
                float _Gloss;
                float _Shininess;
                fixed4 _SpecColor;
    
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    float2 uv : TEXCOORD0;
                    float3 normal : TEXCOORD1;
                    float3 lightDir : TEXCOORD2;                // 光照方向
                    float3 reflectLightDir : TEXCOORD3;            // 光照反射方向
                    float3 viewDir : TEXCOORD4;                    // 视线方向
                };
    
                v2f vert(appdata_full v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    o.normal = v.normal;
                    // 从顶点位置到light的局部向量
                    o.lightDir = ObjSpaceLightDir(v.vertex);
                    // 反射向量,注意需要使用-o.lightDir
                    o.reflectLightDir = reflect(-o.lightDir, v.normal);
                    // 视线,顶点到camera的局部变量
                    o.viewDir = ObjSpaceViewDir(v.vertex);
                    return o;
                }
    
                float4 frag(v2f i) : COLOR
                {
                    i.lightDir = normalize(i.lightDir);
                    i.normal = normalize(i.normal);
                    i.reflectLightDir = normalize(i.reflectLightDir);
                    i.viewDir = normalize(i.viewDir);
    
                    // 纹理采样
                    float4 c = tex2D(_MainTex, i.uv);
                    // 漫射光强度
                    float diffuse = max(0, dot(i.normal, i.lightDir));
    
                    // 镜面光强度
                    float specular = max(0, dot(i.reflectLightDir, i.viewDir));
                    specular = pow(specular, _Shininess) * _Gloss;
                    // 纹理色 * 光源色 * 强度参数
                    c = (c * diffuse + _SpecColor * specular) * _LightColor0;
    
                    return c;
                }
                ENDCG
            }
        }
        FallBack "Diffuse"
    }

    BlinnPhong光照模型,根据光照向量和视线的半角向量,与顶点法线的夹角来计算镜面高光的强度,另外再加上漫射光的成分:

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "James/BlinnPhong"
    {
        Properties
        {
            _MainTex("MainTex", 2D) = "white" {}
            _Gloss("Gloss", Float) = 5
            _Shininess("Shininess", Float) = 10
            _SpecColor("Specular Color", Color) = (1,1,1,1)
        }
            SubShader
            {
                Pass
                {
                    Tags { "LightMode" = "ForwardBase" }
                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #include "UnityCG.cginc"
    
                    fixed4 _LightColor0;
                    sampler2D _MainTex;
                    float4 _MainTex_ST;
                    float _Gloss;
                    float _Shininess;
                    fixed4 _SpecColor;
    
                    struct v2f
                    {
                        float4 pos : SV_POSITION;
                        float2 uv : TEXCOORD0;
                        float3 normal : TEXCOORD1;
                        float3 lightDir : TEXCOORD2;        // 光照方向
                        float3 viewDir : TEXCOORD3;                // 视线方向
                    };
    
                    v2f vert(appdata_full v)
                    {
                        v2f o;
                        o.pos = UnityObjectToClipPos(v.vertex);
                        o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                        o.normal = v.normal;
                        // 顶点->light的局部向量
                        o.lightDir = ObjSpaceLightDir(v.vertex);
                        // 顶点->camera的局部向量
                        float3 viewDir = ObjSpaceViewDir(v.vertex);
                        // 视线,顶点到camera的局部变量
                        o.viewDir = ObjSpaceViewDir(v.vertex);
                        return o;
                    }
    
                    float4 frag(v2f i) : COLOR
                    {
                        i.lightDir = normalize(i.lightDir);
                        i.normal = normalize(i.normal);
                        i.viewDir = normalize(i.viewDir);
                        // 半角向量,光照方向和视线的中间值
                        float3 halfDir = (i.lightDir + i.viewDir) * 0.5;
                        halfDir = normalize(halfDir);
    
                        // 纹理采样
                        float4 c = tex2D(_MainTex, i.uv);
                        // 漫射光强度
                        float diffuse = max(0, dot(i.normal, i.lightDir));
    
                        // 镜面光强度
                        float specular = max(0, dot(i.normal, halfDir));
                        specular = pow(specular, _Shininess) * _Gloss;
    
                        // 纹理色 * 光源色 * 强度参数
                        c = (c * diffuse + _SpecColor * specular) * _LightColor0;
                        return c;
                    }
                    ENDCG
                }
            }
                FallBack "Diffuse"
    }

    BinnPhong比Phong少计算一次反射向量,会更简洁和高效。

    带光源衰减的计算方式:

    Shader "James/Direct2"
    {
        Properties
        {
            _Color("Color",Color) = (1,1,1,1)
            _SpecularColor("Specular",Color) = (1,1,1,1)
            _Gloss("Gloss",Range(8.0,256)) = 20
        }
    
        SubShader
        {
            Pass
            {
                Tags{"LightMode" = "ForwardBase"}
    
                CGPROGRAM
                #pragma multi_compile_fwdbase
                #pragma vertex vert
                #pragma fragment frag
    
                #include "Lighting.cginc"
                #include "AutoLight.cginc" 
                //计算阴影所用的宏包含在AutoLight.cginc文件中
    
                fixed4 _Color;
                fixed4 _SpecularColor;
                float _Gloss;
    
                struct a2v
                {
                    float4  vertex:POSITION;
                    float3  normal:NORMAL;
                };
    
                struct v2f 
                {
                    float4 pos:SV_POSITION;
                    float3 worldPos:TEXCOORD0;
                    float3 worldNormal:TEXCOORD1;
                    SHADOW_COORDS(2)
                    //该宏的作用是声明一个用于对阴影纹理采样的坐标
                    //这个宏的参数是下一个可用的插值寄存器的索引值,上述中为2
                };
    
                v2f vert(a2v v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                    o.worldNormal = UnityObjectToWorldNormal(v.normal);
    
                    TRANSFER_SHADOW(o);
                    //该宏用于计算上一步声明的阴影纹理采样坐标
    
                    return o;
                }
    
                fixed4 frag(v2f i) :SV_Target
                {
                    float3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                    float3 worldNormal = normalize(i.worldNormal);
                    float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
    
                    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                    fixed3 diffuse = _LightColor0.rgb*_Color.rgb*max(0,dot(worldLightDir,worldNormal));
                    fixed3 halfDir = normalize(worldLightDir + worldViewDir);
                    fixed3 specularColor = _LightColor0.rgb*_SpecularColor.rgb*pow(saturate(dot(halfDir,worldNormal)),_Gloss);
    
                    fixed shadow = SHADOW_ATTENUATION(i);
                    //片元着色器中计算阴影值
    
                    fixed atten = 1.0;
                    return fixed4(ambient + (diffuse + specularColor)*atten*shadow,1.0);
                }
                ENDCG
            }
    
            Pass
            {
                Tags{"LightMode" = "ForwardAdd"}
                Blend One One
                CGPROGRAM
                #pragma multi_compile_fwdadd
                #pragma vertex vert
                #pragma fragment frag
    
                #include "Lighting.cginc"
                #include "AutoLight.cginc"
    
                fixed4 _Color;
                fixed4 _SpecularColor;
                float   _Gloss;
    
                struct a2v
                {
                    float4  vertex:POSITION;
                    float3  normal:NORMAL;
                };
    
                struct v2f
                {
                    float4 pos:SV_POSITION;
                    float3 worldPos:TEXCOORD0;
                    float3 worldNormal:TEXCOORD1;
                };
    
                v2f vert(a2v v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
                    o.worldNormal = UnityObjectToWorldNormal(v.normal);
    
                    return o;
                }
    
                fixed4 frag(v2f i) :SV_Target
                {
                    #ifdef USING_DIRECTIONAL_LIGHT
                        fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
                        fixed atten = 1.0;
                    #else
                        fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos.xyz);
                        float3 lightCoord = mul(unity_WorldToLight,float4(i.worldPos,1.0)).xyz;
                        fixed atten = tex2D(_LightTexture0,dot(lightCoord,lightCoord).rr).UNITY_ATTEN_CHANNEL;
                    #endif
                    float3 worldNormal = normalize(i.worldNormal);
                    float3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
    
                    fixed3 diffuse = _LightColor0.rgb*_Color.rgb*max(0,dot(worldLightDir,worldNormal));
                    fixed3 halfDir = normalize(worldLightDir + worldViewDir);
                    fixed3 specularColor = _LightColor0.rgb*_SpecularColor.rgb*pow(saturate(dot(halfDir,worldNormal)),_Gloss);
    
    
                    return fixed4((diffuse + specularColor)*atten,1.0);
                }
                ENDCG
            }
        }
        FallBack "Specular"
    }

    参考:https://blog.csdn.net/u013477973/article/details/80639969

  • 相关阅读:
    通过SSIS监控远程服务器Windows服务并发送邮件报警!
    通过SSIS监控远程服务器磁盘空间并发送邮件报警!
    Jquery和雅虎的YQL服务实现天气预报功能!
    表字段或表名出现Mysql关键字或保留字导致问题 Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have
    Mybatis对象关系映射 one2one,one2many,many2many
    事务的传播属性及隔离级别 Spring
    正整数的二进制表示中1的个数计算(使用移位或者n&(n-1))
    char类型及ASCII码之间比较
    数据表记录包含表索引和数值(int范围的整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出
    写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。(多组同时输入 )
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/4773652.html
Copyright © 2020-2023  润新知