Phong 光照模型

1、原理

物体表面反射光线是由三部分组成:环境光 + 漫反射光 + 镜面反射光(高光反射光)

2、Shader 中的环境光

环境光变量其实是可以在Unity中进行设置的

Window——> Rendering——> Lighting
Environment(环境)页签中的Environment Lighting(环境光)
这里可以设置环境光来源
当是Skybox和Color时,我们可以通过 UNITY_LIGHTMODEL_AMBIENT 获取到对应环境光颜色
当是Gradient(渐变)时,通过以下3个成员可以得到对应的环境光

  •     unity_AmbientSky(周围的天空环境光)
  •     unity_AmbientEquator(周围的赤道环境光)
  •     unity_AmbientGround(周围的地面环境光)

3、Phong光照模型的公式

物体表面光照颜色 = 环境光颜色 + 漫反射光颜色 + 高光反射光颜色
其中:

  • 环境光颜色 = UNITY_LIGHTMODEL_AMBIENT(unity_AmbientSky、unity_AmbientEquator、unity_AmbientGround)
  • 漫反射光颜色 = 兰伯特光照模型 计算得到的颜色
  • 高光反射光颜色 = Phong式高光反射光照模型 计算得到的颜色

PS:两个颜色相乘和相加的区别

相乘: 颜色相乘时,最终颜色会往黑色靠拢,计算两个颜色混合时一般用颜色相乘,因为真实世界中多个颜色混在一起最终会变成黑色

相加: 颜色相加时,最终颜色会往白色靠拢,计算光照反射时一般用颜色相加,因为向白色靠拢能带来 更亮的感觉,复合光的表现

4、逐顶点光照

Shader "ShaderProj/1/Phong_vertex"
{
    Properties
    {
        _MainColor("_MainColor", Color)=(1,1,1,1)
        _SpecularColor("_SpecularColor", Color)=(1,1,1,1)
        _SpecularNum("_SpecularNum", Range(0,30)) = 0.5
    }
    SubShader
    {
        Tags { "LightMode"="ForwardBase" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct v2f
            {
                float4 pos:SV_POSITION;
                fixed3 color:COLOR;
            };
            fixed3 _MainColor;
            fixed3 _SpecularColor;
            float _SpecularNum;

            // lambert function
            fixed3 getLambertColor(in float3 objNormal)
            {
                float3 normal = UnityObjectToWorldNormal(objNormal);
                float3 lightDir = normalize(_WorldSpaceLightPos0);
                fixed3 color = _LightColor0.rgb * _MainColor.rgb * max(0, dot(normal, lightDir));
                return color;
            }

            // phong specular function
            fixed3 getSpecularColor(in float4 pos, in float3 objNormal)
            {
                float3 worldPos = mul(unity_ObjectToWorld, pos);
                float3 normal = UnityObjectToWorldNormal(objNormal);
                float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - worldPos);
                float3 lightDir = normalize(_WorldSpaceLightPos0);
                float3 reflectDir = reflect(-lightDir, normal);
                fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
                return color;
            }

            v2f vert (appdata_base v)
            {
                v2f data;

                data.pos = UnityObjectToClipPos(v.vertex);
                fixed3 lambertColor = getLambertColor(v.normal);
                fixed3 specularColor = getSpecularColor(v.vertex, v.normal);
                data.color  = lambertColor + specularColor + UNITY_LIGHTMODEL_AMBIENT;

                return data;               
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(i.color, 1);
            }
            ENDCG
        }
    }
}

5、逐片元光照

Shader "ShaderProj/1/Phong_frag"
{
    Properties
    {
        _MainColor("_MainColor", Color)=(1,1,1,1)
        _SpecularColor("_SpecularColor", Color)=(1,1,1,1)
        _SpecularNum("_SpecularNum", Range(0, 30))=0.5
    }
    SubShader
    {
        Tags {"LightMode"="ForwardBase" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"

            struct v2f
            {
                float4 pos:SV_POSITION;
                float3 normal:NORMAL;
                float4 wPos:TEXCOORD0;
            };
            fixed3 _MainColor;
            fixed3 _SpecularColor;
            float _SpecularNum;

            fixed3 getLambertColor(in float3 normal)
            {
                float3 lightDir = normalize(_WorldSpaceLightPos0);
                fixed3 color = _LightColor0.rgb * _MainColor.rgb * max(0, dot(normal, lightDir));
                return color;
            }

            fixed3 getSpecularColor(in float3 worldPos, in float3 normal)
            {
                float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
                float3 lightDir = normalize(_WorldSpaceLightPos0);
                float3 reflectDir = reflect(-lightDir, normal);
                fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
                return color;
            }

            v2f vert (appdata_base v)
            {
                v2f data;
                data.pos = UnityObjectToClipPos(v.vertex);
                data.wPos = mul(unity_ObjectToWorld, v.vertex);
                data.normal = UnityObjectToWorldNormal(v.normal);
                
                return data;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 lambertColor = getLambertColor(i.normal);
                fixed3 specularColor = getSpecularColor(i.wPos, i.normal);
                fixed3 color = lambertColor + specularColor + UNITY_LIGHTMODEL_AMBIENT;
                return fixed4(color, 1);
            }
            ENDCG
        }
    }
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值