Phong 式光照模型

概述

Phong认为物体表面反射光线是由三部分组成的:

环境光 + 漫反射光 + 镜面反射光(高光反射光)

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

环境光颜色 = UNITY_LIGHTMODEL_AMBIENT

漫反射光颜色 = 兰伯特光照模型计算的颜色

高光反射光颜色 = Phong式高光反射模型计算的颜色

颜色相乘与相加

  • 颜色相乘时,最终颜色会往黑色靠拢,计算两个颜色混合时一般用颜色相乘
  • 颜色相加时,最终颜色会往白色靠拢,计算光照反射时一般用颜色相加

ShaderLab示例

Phong式光照模型逐顶点光照

SubShader
{
    Pass
    {
        Tags
        {
            "LightMode" = "ForwardBase"
        }

        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        #include "UnityCG.cginc"
        #include "Lighting.cginc"

        // 材质漫反射颜色
        fixed4 _MainColor;
        fixed4 _SpecularColor;
        float _SpecularLevel;

        // 顶点着色器传递给片元着色器的内容
        struct v2f
        {
            // 裁剪空间下的顶点坐标信息
            float4 pos: SV_POSITION;
            // 对应顶点的漫反射光照颜色
            fixed3 color: COLOR;
        };

        // 计算兰伯特光照模型
        fixed3 getLamebrtColor(in float3 objNormal)
        {
            // 获取世界坐标下的法线信息
            float3 normal = UnityObjectToWorldNormal(objNormal);
            // 获取归一化的光源方向
            float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
            fixed3 color = _LightColor0.rgb * _MainColor * max(0, dot(normal, lightDir));
            return color;
        }

        // 计算Phong式高光反射
        fixed3 getPhongSpecularColor(in float4 objVertex, in float3 objNormal)
        {
            // 将模型空间下的顶点位置转换到世界空间下
            float3 worldPos = mul(UNITY_MATRIX_M, objVertex);
            // 获取标准化观察方向向量
            float3 viewDir = _WorldSpaceCameraPos.xyz - worldPos;
            viewDir = normalize(viewDir);
            // 获取标准化反射方向向量
            float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
            float3 normal = UnityObjectToWorldNormal(objNormal);
            float3 reflectDir = reflect(-lightDir, normal);
            fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(
                max(0, dot(viewDir, reflectDir)), _SpecularLevel);
            return color;
        }

        v2f vert(appdata_base v)
        {
            v2f o;
            // 模型空间下的顶点转换到世界坐标系
            o.pos = UnityObjectToClipPos(v.vertex);
            // 计算兰伯特光照模型颜色
            fixed3 lambertColor = getLamebrtColor(v.normal);
            // 计算Phong式高光反射颜色
            fixed3 phongSpecularColor = getPhongSpecularColor(v.vertex, v.normal);
            o.color = UNITY_LIGHTMODEL_AMBIENT + lambertColor + phongSpecularColor;
            return o;
        }

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

Phong式光照模型逐片元光照

SubShader
{
    Pass
    {
        Tags
        {
            "LightMode" = "ForwardBase"
        }

        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag

        #include "UnityCG.cginc"
        #include "Lighting.cginc"

        // 材质漫反射颜色
        fixed4 _MainColor;
        fixed4 _SpecularColor;
        float _SpecularLevel;

        // 顶点着色器传递给片元着色器的内容
        struct v2f
        {
            // 裁剪空间下的顶点坐标信息
            float4 pos: SV_POSITION;
            // 世界空间下的法线信息
            fixed3 wNormal : NORMAL;
            // 世界空间下的顶点坐标
            float3 wPos : TEXCOORD0;
        };

        // 计算兰伯特光照模型
        fixed3 getLamebrtColor(in float3 normal)
        {
            // 获取归一化的光源方向
            float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
            fixed3 color = _LightColor0.rgb * _MainColor * max(0, dot(normal, lightDir));
            return color;
        }

        // 计算Phong式高光反射
        fixed3 getPhongSpecularColor(in float3 wVertexPos, in float3 wNormal)
        {
            // 获取标准化观察方向向量
            float3 viewDir = _WorldSpaceCameraPos.xyz - wVertexPos;
            viewDir = normalize(viewDir);
            // 获取标准化反射方向向量
            float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
            float3 normal = UnityObjectToWorldNormal(wNormal);
            float3 reflectDir = reflect(-lightDir, normal);
            fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(
                max(0, dot(viewDir, reflectDir)), _SpecularLevel);
            return color;
        }

        v2f vert(appdata_base v)
        {
            v2f o;
            // 模型空间下的顶点转换到世界坐标系
            o.pos = UnityObjectToClipPos(v.vertex);
            o.wNormal = UnityObjectToWorldNormal(v.normal);
            o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
            return o;
        }

        fixed4 frag(v2f i) : SV_Target
        {
            // 计算兰伯特光照模型颜色
            fixed3 lambertColor = getLamebrtColor(i.wNormal);
            // 计算Phong式高光反射颜色
            fixed3 phongSpecularColor = getPhongSpecularColor(i.wPos, i.wNormal);
            fixed3 color = UNITY_LIGHTMODEL_AMBIENT + lambertColor + phongSpecularColor;
            return fixed4(color.rgb, 1);
        }
        ENDCG
    }
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇